iobroker.javascript 10.2.4 → 10.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (186) hide show
  1. package/README.md +10 -21
  2. package/admin/assets/AiChatPanel-CpY4Bun-.js +27 -0
  3. package/admin/assets/{AiChatService-Bsp_rhVx.js → AiChatService-QKcpW4jQ.js} +1 -1
  4. package/admin/assets/AiDiffView-DscPfZ38.js +1 -0
  5. package/admin/assets/{AiInlineProvider-BxOW88xU.js → AiInlineProvider-DTSPKoXG.js} +1 -1
  6. package/admin/assets/BlocklyEditor-BZyoN1JE.js +301 -0
  7. package/admin/assets/Compile-B0uHjrBE.css +1 -0
  8. package/admin/assets/Compile-Oss28m_f.js +165 -0
  9. package/admin/assets/Debugger-teJTIU-2.js +15 -0
  10. package/admin/assets/Documentation-uz4Ut9pT.js +4339 -0
  11. package/admin/assets/ExpandMore-V5Ix1QB1.js +1 -0
  12. package/admin/assets/FbEditor-B8S-mCvc.css +1 -0
  13. package/admin/assets/FbEditor-aOZ-RpPV.js +15 -0
  14. package/admin/assets/Import-BIC5Ee9z.js +1 -0
  15. package/admin/assets/NotificationsActive-BdzH44gp.js +1 -0
  16. package/admin/assets/RulesEditor-CcDVthPa.js +1 -0
  17. package/admin/assets/{ScriptEditor-BCGahS47.js → ScriptEditor-CviB6Hif.js} +2 -2
  18. package/admin/assets/ScriptEditorVanillaMonaco-ByuXwybM.js +3 -0
  19. package/admin/assets/Send-Mdo32jMb.js +1 -0
  20. package/admin/assets/_virtual_mf-localSharedImportMap___mfe_internal__iobroker_javascript__mf_owner__1-BnL93BgK.js +1 -0
  21. package/admin/assets/_virtual_mf___mfe_internal__iobroker_javascript__mf_owner__180366418666083__loadShare___mf_0_iobroker_mf_1_gui_mf_2_components__loadShare__.js-NI-3Uv4e.js +1217 -0
  22. package/admin/assets/_virtual_mf___mfe_internal__iobroker_javascript__mf_owner__180366418666083__loadShare__react_mf_2_dom_mf_1_client__loadShare__.js-DVaMIZyC.js +9 -0
  23. package/admin/assets/aiPromptBuilder-yTB6N2VT.js +1 -0
  24. package/admin/assets/blocklyTheme-CGhU3cEO.js +1 -0
  25. package/admin/assets/blocks_action-BQ4O7NRE.js +1 -0
  26. package/admin/assets/{blocks_convert-CLb0DLyc.js → blocks_convert-0VBjfhqQ.js} +1 -1
  27. package/admin/assets/blocks_logic-DAo99xDr.js +1 -0
  28. package/admin/assets/blocks_number-C--e19NU.js +1 -0
  29. package/admin/assets/blocks_object-D0TPhdzg.js +1 -0
  30. package/admin/assets/blocks_procedures-DgTxgXdB.js +3 -0
  31. package/admin/assets/{blocks_sendto-BxCMg9X4.js → blocks_sendto-CRIrtOUc.js} +1 -1
  32. package/admin/assets/blocks_switch-b_GYfF0n.js +2 -0
  33. package/admin/assets/blocks_system-BdkUdSsc.js +1 -0
  34. package/admin/assets/blocks_text-DSFhEVOf.js +1 -0
  35. package/admin/assets/blocks_time-CqALAiJp.js +1 -0
  36. package/admin/assets/blocks_timeout-yrOD2pZp.js +1 -0
  37. package/admin/assets/{blocks_trigger-XivsIDE5.js → blocks_trigger-DeAYXpSS.js} +1 -1
  38. package/admin/assets/{cronHoverProvider-BZMOFHO_.js → cronHoverProvider-DoO2_tpG.js} +1 -1
  39. package/admin/assets/{field_cron-CxKi__cX.js → field_cron-D3Ts_s9M.js} +1 -1
  40. package/admin/assets/{field_oid-CJIYiGxY.js → field_oid-BRNXredg.js} +1 -1
  41. package/admin/assets/{field_script-CehplM7L.js → field_script-3X6ousg7.js} +1 -1
  42. package/admin/assets/helpers-BTGaTdnT.js +1 -0
  43. package/admin/assets/{hostInit-Bs-bStPF.js → hostInit-2h2Cbsaw.js} +1 -1
  44. package/admin/assets/iconLibraryData-B5fiyl1C.js +1 -0
  45. package/admin/assets/index-BHhhebRG.css +1 -0
  46. package/admin/assets/index-CbQlIKB_.js +156 -0
  47. package/admin/assets/{inlineChatWidget-NIvdRGmU.js → inlineChatWidget-BwQVCPkx.js} +1 -1
  48. package/admin/assets/{inlineDiffController-Qh402KhK.js → inlineDiffController-BsDDsDHn.js} +1 -1
  49. package/admin/assets/loadBlocks-RpqM7PwO.js +117 -0
  50. package/admin/assets/loadMonaco-BVOEahNw.js +1 -0
  51. package/admin/assets/{mf-entry-bootstrap-0-019228a5.js → mf-entry-bootstrap-0-0deef484.js} +3 -3
  52. package/admin/assets/{pendingShares-B3t6ewri.js → pendingShares-BaAadIDv.js} +1 -1
  53. package/admin/assets/reactour.esm-DX9ZgYlx.js +137 -0
  54. package/admin/assets/stateHoverProvider-BEadnSXp.js +11 -0
  55. package/admin/assets/tileFbd-CWAy7R7m.svg +85 -0
  56. package/admin/custom/assets/Components-FkGDIlId.js +1 -0
  57. package/admin/custom/assets/_virtual_mf-localSharedImportMap___mfe_internal__ConfigCustomJavascriptSet__mf_owner__1-Cs88NUCd.js +1 -0
  58. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__37453319418803__loadShare___mf_0_emotion_mf_1_react__loadShare__.js-P-8ffWXw.js +1 -0
  59. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__37453319418803__loadShare___mf_0_emotion_mf_1_styled__loadShare__.js-ZVuRAEo5.js +1 -0
  60. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__37453319418803__loadShare___mf_0_iobroker_mf_1_gui_mf_2_components__loadShare__.js-DVb0ZZ1Q.js +1217 -0
  61. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__37453319418803__loadShare___mf_0_iobroker_mf_1_json_mf_2_config__loadShare__.js-Dna3WF04.js +1 -0
  62. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__37453319418803__loadShare___mf_0_mui_mf_1_x_mf_2_date_mf_2_pickers__loadShare__.js-DcjdCGAx.js +1 -0
  63. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__37453319418803__loadShare__date_mf_2_fns__loadShare__.js-CnhNjamd.js +1 -0
  64. package/admin/custom/assets/{_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__136440932828998__loadShare__leaflet__loadShare__.js-im3edKNs.js → _virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__37453319418803__loadShare__leaflet__loadShare__.js-Dz7BFJqH.js} +1 -1
  65. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__37453319418803__loadShare__react_mf_2_dom_mf_1_client__loadShare__.js-B0olko2J.js +1 -0
  66. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__37453319418803__prebuild___mf_0_iobroker_mf_1_json_mf_2_config__prebuild__-CzN4reh_.js +122 -0
  67. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__37453319418803__prebuild__leaflet__prebuild__-xPcBaiTQ.js +1 -0
  68. package/admin/custom/assets/{_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__136440932828998__prebuild__react_mf_1_jsx_mf_2_runtime__prebuild__-Byvr2uOb.js → _virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__37453319418803__prebuild__react_mf_1_jsx_mf_2_runtime__prebuild__-CXpyx8Vy.js} +1 -1
  69. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__37453319418803__prebuild__react_mf_2_dom_mf_1_client__prebuild__-DuFBE5fh.js +9 -0
  70. package/admin/custom/assets/{hostInit-IJMNq3h7.js → hostInit-6oh4UY2k.js} +1 -1
  71. package/admin/custom/assets/iconLibraryData-B5fiyl1C.js +1 -0
  72. package/admin/custom/assets/index-BrlyEy6J.js +1 -0
  73. package/admin/custom/assets/lib-BmDlTzq2.js +3 -0
  74. package/admin/custom/assets/{mf-entry-bootstrap-0-f149bc46.js → mf-entry-bootstrap-0-ad1cd7d0.js} +3 -3
  75. package/admin/custom/assets/pendingShares-kV2kwejX.js +1 -0
  76. package/admin/custom/assets/rolldown-runtime-Dqfqb5bO.js +1 -0
  77. package/admin/custom/customComponents.js +3 -2
  78. package/admin/custom/i18n/en.json +39 -39
  79. package/admin/custom/i18n/es.json +1 -1
  80. package/admin/custom/i18n/fr.json +2 -2
  81. package/admin/custom/i18n/it.json +1 -1
  82. package/admin/custom/i18n/nl.json +2 -2
  83. package/admin/custom/i18n/pt.json +2 -2
  84. package/admin/custom/i18n/ru.json +2 -2
  85. package/admin/custom/i18n/uk.json +1 -1
  86. package/admin/custom/i18n/zh-cn.json +1 -1
  87. package/admin/i18n/de.json +1 -1
  88. package/admin/i18n/en.json +115 -115
  89. package/admin/i18n/fr.json +115 -115
  90. package/admin/i18n/it.json +115 -115
  91. package/admin/i18n/nl.json +115 -115
  92. package/admin/i18n/pl.json +1 -1
  93. package/admin/i18n/pt.json +115 -115
  94. package/admin/i18n/ru.json +115 -115
  95. package/admin/i18n/uk.json +115 -115
  96. package/admin/i18n/zh-cn.json +115 -115
  97. package/admin/mf-manifest.json +1 -1
  98. package/admin/mf-stats.json +1 -1
  99. package/admin/remoteEntry.js +2 -2
  100. package/admin/tab.html +3 -7
  101. package/build/lib/fb/analyze.js +288 -0
  102. package/build/lib/fb/analyze.js.map +1 -0
  103. package/build/lib/fb/blocks.js +605 -0
  104. package/build/lib/fb/blocks.js.map +1 -0
  105. package/build/lib/fb/generate.js +326 -0
  106. package/build/lib/fb/generate.js.map +1 -0
  107. package/build/lib/fb/graph.js +240 -0
  108. package/build/lib/fb/graph.js.map +1 -0
  109. package/build/lib/fb/index.js +57 -0
  110. package/build/lib/fb/index.js.map +1 -0
  111. package/build/lib/fb/js.js +33 -0
  112. package/build/lib/fb/js.js.map +1 -0
  113. package/build/lib/fb/layout.js +205 -0
  114. package/build/lib/fb/layout.js.map +1 -0
  115. package/build/lib/fb/library.js +657 -0
  116. package/build/lib/fb/library.js.map +1 -0
  117. package/build/lib/fb/runtime.js +793 -0
  118. package/build/lib/fb/runtime.js.map +1 -0
  119. package/build/lib/fb/time.js +76 -0
  120. package/build/lib/fb/time.js.map +1 -0
  121. package/build/lib/fb/types.js +19 -0
  122. package/build/lib/fb/types.js.map +1 -0
  123. package/build/lib/fb/user.js +78 -0
  124. package/build/lib/fb/user.js.map +1 -0
  125. package/build/lib/javascript.d.ts +17 -17
  126. package/build/lib/mirror.js +4 -0
  127. package/build/lib/mirror.js.map +1 -1
  128. package/build/lib/sandbox.js +44 -0
  129. package/build/lib/sandbox.js.map +1 -1
  130. package/build/main.js +66 -1
  131. package/build/main.js.map +1 -1
  132. package/build/types.d.ts +9 -1
  133. package/docs/de/README.md +1 -1
  134. package/docs/de/fbd.md +274 -0
  135. package/docs/de/javascript.md +2167 -0
  136. package/docs/en/fbd.md +260 -0
  137. package/docs/en/javascript.md +28 -30
  138. package/io-package.json +52 -28
  139. package/package.json +8 -8
  140. package/admin/assets/AiChatPanel-AZko1BsN.js +0 -27
  141. package/admin/assets/AiDiffView-Cri2QFh1.js +0 -1
  142. package/admin/assets/Debugger-CVDh3kgz.js +0 -15
  143. package/admin/assets/Error-Ch2nx5uC.js +0 -1
  144. package/admin/assets/Import-XKVP-nRT.js +0 -1
  145. package/admin/assets/RulesEditor-DsO4cKIk.js +0 -1
  146. package/admin/assets/ScriptEditorVanillaMonaco-BDAw2Bw6.js +0 -3
  147. package/admin/assets/_virtual_mf-localSharedImportMap___mfe_internal__iobroker_javascript__mf_owner__1-BMAFQFoH.js +0 -1
  148. package/admin/assets/_virtual_mf___mfe_internal__iobroker_javascript__mf_owner__113183188387379__loadShare___mf_0_iobroker_mf_1_gui_mf_2_components__loadShare__.js-D-gi6Mty.js +0 -1217
  149. package/admin/assets/_virtual_mf___mfe_internal__iobroker_javascript__mf_owner__113183188387379__loadShare__react_mf_2_dom_mf_1_client__loadShare__.js-CDctpiPx.js +0 -9
  150. package/admin/assets/aiPromptBuilder-aJfHa-eU.js +0 -1
  151. package/admin/assets/blocks_action-DS28sNfo.js +0 -1
  152. package/admin/assets/blocks_logic-Dpp2fwlu.js +0 -1
  153. package/admin/assets/blocks_number-N4IfHvYD.js +0 -1
  154. package/admin/assets/blocks_object-uK7FHVhS.js +0 -1
  155. package/admin/assets/blocks_procedures-C_KD0Bm6.js +0 -3
  156. package/admin/assets/blocks_switch-C8Rls5pK.js +0 -2
  157. package/admin/assets/blocks_system-CEQnj5fY.js +0 -1
  158. package/admin/assets/blocks_text-BDEWxu0P.js +0 -1
  159. package/admin/assets/blocks_time-aHQQK1Uz.js +0 -1
  160. package/admin/assets/blocks_timeout-C2L93TLJ.js +0 -1
  161. package/admin/assets/helpers-DiwtLpXM.js +0 -1
  162. package/admin/assets/index-B0FfAYMN.js +0 -871
  163. package/admin/assets/index-CXaeqPRy.css +0 -1
  164. package/admin/assets/stateHoverProvider-BkW15VMN.js +0 -9
  165. package/admin/assets/virtualExposes-DgGB-18P.js +0 -1
  166. package/admin/assets/virtual_mf-REMOTE_ENTRY_ID___mfe_internal__iobroker_javascript__remoteEntry_js-CiidVc0O.js +0 -1
  167. package/admin/assets/virtual_mf-exposes___mfe_internal__iobroker_javascript__remoteEntry_js-ChiJXsfH.js +0 -1
  168. package/admin/custom/assets/Components-SGnA-3W_.js +0 -1
  169. package/admin/custom/assets/_virtual_mf-localSharedImportMap___mfe_internal__ConfigCustomJavascriptSet__mf_owner__1-Bx3X6TLB.js +0 -1
  170. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__136440932828998__loadShare___mf_0_emotion_mf_1_react__loadShare__.js-Cc7MmJgr.js +0 -1
  171. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__136440932828998__loadShare___mf_0_emotion_mf_1_styled__loadShare__.js-CdvEvX5z.js +0 -1
  172. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__136440932828998__loadShare___mf_0_iobroker_mf_1_gui_mf_2_components__loadShare__.js-D5NaoeJi.js +0 -1217
  173. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__136440932828998__loadShare___mf_0_iobroker_mf_1_json_mf_2_config__loadShare__.js-Cbgw_a3f.js +0 -1
  174. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__136440932828998__loadShare___mf_0_mui_mf_1_x_mf_2_date_mf_2_pickers__loadShare__.js-CMr75K5w.js +0 -1
  175. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__136440932828998__loadShare__date_mf_2_fns__loadShare__.js-DKIvPDPX.js +0 -1
  176. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__136440932828998__loadShare__react_mf_2_dom_mf_1_client__loadShare__.js-D50aYKgD.js +0 -1
  177. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__136440932828998__prebuild___mf_0_iobroker_mf_1_json_mf_2_config__prebuild__-CEzQFX7o.js +0 -122
  178. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__136440932828998__prebuild__leaflet__prebuild__-BUDmnAcx.js +0 -1
  179. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__136440932828998__prebuild__react_mf_2_dom_mf_1_client__prebuild__-D_1oh1WH.js +0 -9
  180. package/admin/custom/assets/index-7r4VklMp.js +0 -1
  181. package/admin/custom/assets/lib-DDU2Oe48.js +0 -3
  182. package/admin/custom/assets/pendingShares-DarGQhyO.js +0 -1
  183. package/admin/custom/assets/rolldown-runtime-BcKkbAw3.js +0 -1
  184. package/admin/custom/assets/virtualExposes-C0IqMANQ.js +0 -1
  185. package/admin/custom/assets/virtual_mf-REMOTE_ENTRY_ID___mfe_internal__ConfigCustomJavascriptSet__customComponents_js-CqKvh5Xu.js +0 -1
  186. package/admin/custom/assets/virtual_mf-exposes___mfe_internal__ConfigCustomJavascriptSet__customComponents_js-DrBN_S5o.js +0 -2
@@ -0,0 +1,605 @@
1
+ "use strict";
2
+ /**
3
+ * The blocks of the library that remember something, and the conversions of the generated code.
4
+ *
5
+ * Pure code without Node or the DOM: fb-runtime hands them to the generated code, and the editor
6
+ * runs the same classes for the preview of a block - so the two never tell different stories.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.JS = exports.BLINK = exports.CTUD = exports.CTD = exports.CTU = exports.SCHEDULE = exports.CLOCK = exports.SENDTO = exports.NOTIFY = exports.LOG = exports.PID = exports.PT1 = exports.RAMP = exports.HYST = exports.TP = exports.TOF = exports.TON = exports.F_TRIG = exports.R_TRIG = exports.SR = exports.RS = exports.JsBlock = exports.MessageBlock = exports.MESSAGE_LIMIT = exports.LOG_LIMIT = exports.BlinkBlock = exports.CtudBlock = exports.CtdBlock = exports.CtuBlock = exports.PidBlock = exports.Pt1Block = exports.RampBlock = exports.HystBlock = exports.TpBlock = exports.TofBlock = exports.TonBlock = exports.FTrigBlock = exports.RTrigBlock = exports.SrBlock = exports.RsBlock = exports.ScheduleBlock = exports.ClockBlock = void 0;
10
+ exports.toBool = toBool;
11
+ exports.toNum = toNum;
12
+ exports.div = div;
13
+ exports.toReal = toReal;
14
+ exports.toInt = toInt;
15
+ exports.toTime = toTime;
16
+ exports.toStr = toStr;
17
+ exports.concat = concat;
18
+ exports.round = round;
19
+ exports.timeOfDay = timeOfDay;
20
+ exports.inWindow = inWindow;
21
+ exports.timeWindow = timeWindow;
22
+ const time_1 = require("./time");
23
+ // ---- conversions
24
+ function toBool(value) {
25
+ if (typeof value === 'string') {
26
+ const text = value.trim().toLowerCase();
27
+ return text === 'true' || text === 'on' || text === '1' || text === 'yes';
28
+ }
29
+ return !!value;
30
+ }
31
+ function toNum(value) {
32
+ if (typeof value === 'boolean') {
33
+ return value ? 1 : 0;
34
+ }
35
+ const number = typeof value === 'number' ? value : parseFloat(String(value));
36
+ return Number.isFinite(number) ? number : NaN;
37
+ }
38
+ /** A division that gives 0 instead of Infinity or NaN for a divisor of 0 */
39
+ function div(a, b) {
40
+ return b ? a / b : 0;
41
+ }
42
+ /** A number of TO_REAL: a decimal comma counts as a point, what is no number gives 0 */
43
+ function toReal(value) {
44
+ const number = toNum(typeof value === 'string' ? value.replace(',', '.') : value);
45
+ return Number.isNaN(number) ? 0 : number;
46
+ }
47
+ /** A whole number of TO_INT: rounded, as REAL_TO_INT of IEC does */
48
+ function toInt(value) {
49
+ return Math.round(toReal(value));
50
+ }
51
+ /** A time of TO_TIME: a number is ms, a text may be `2s` or `08:30` as well; what is no time gives 0 */
52
+ function toTime(value) {
53
+ if (typeof value === 'string') {
54
+ return (0, time_1.parseTime)(value) ?? (0, time_1.parseTime)(toReal(value)) ?? 0;
55
+ }
56
+ return (0, time_1.parseTime)(toReal(value)) ?? 0;
57
+ }
58
+ /** A value as text: numbers and booleans as with String(), objects as JSON */
59
+ function toStr(value) {
60
+ switch (typeof value) {
61
+ case 'string':
62
+ return value;
63
+ case 'number':
64
+ case 'boolean':
65
+ return value.toString();
66
+ case 'undefined':
67
+ return '';
68
+ default:
69
+ return value === null ? '' : JSON.stringify(value);
70
+ }
71
+ }
72
+ /** All inputs of CONCAT as one text */
73
+ function concat(...values) {
74
+ return values.map(toStr).join('');
75
+ }
76
+ /**
77
+ * Rounded to `digits` decimals, 0 to 10. Through the exponent of the text, so `1.005` gives `1.01`
78
+ * and not `1` as `Math.round(1.005 * 100) / 100` would.
79
+ */
80
+ function round(value, digits) {
81
+ const places = Math.max(0, Math.min(10, Math.round(digits) || 0));
82
+ if (!Number.isFinite(value)) {
83
+ return 0;
84
+ }
85
+ const rounded = Number(`${Math.round(Number(`${value}e${places}`))}e-${places}`);
86
+ // a number that is written with an exponent already, like 1e-7, does not take one more
87
+ return Number.isFinite(rounded) ? rounded : Math.round(value * 10 ** places) / 10 ** places;
88
+ }
89
+ // ---- time of day
90
+ /** The time of day in ms since the local midnight */
91
+ function timeOfDay(now = Date.now()) {
92
+ const date = new Date(now);
93
+ return ((date.getHours() * 60 + date.getMinutes()) * 60 + date.getSeconds()) * 1000 + date.getMilliseconds();
94
+ }
95
+ /**
96
+ * Whether a time of day lies in the window from `start` to `end` - including the start, not the
97
+ * end. A window with `start` after `end` goes over midnight; `start` equal to `end` is empty.
98
+ */
99
+ function inWindow(time, start, end) {
100
+ return start <= end ? time >= start && time < end : time >= start || time < end;
101
+ }
102
+ /** Days of TIMEWINDOW */
103
+ const DAYS = {
104
+ all: () => true,
105
+ // getDay(): 0 is Sunday
106
+ weekdays: day => day >= 1 && day <= 5,
107
+ weekend: day => day === 0 || day === 6,
108
+ };
109
+ /**
110
+ * TIMEWINDOW: whether now is between `start` and `end` on the days `days` (`all`, `weekdays`,
111
+ * `weekend`). A window over midnight belongs to the day it starts on: Friday 22:00 to 06:00 lasts
112
+ * until Saturday 06:00, and Monday 00:00 to 06:00 belongs to Sunday.
113
+ */
114
+ function timeWindow(start, end, days, now = Date.now()) {
115
+ const time = timeOfDay(now);
116
+ if (!inWindow(time, start, end)) {
117
+ return false;
118
+ }
119
+ const day = new Date(now).getDay();
120
+ const isDay = DAYS[days] || DAYS.all;
121
+ // after midnight in a window that started the day before
122
+ return isDay(start > end && time < end ? (day + 6) % 7 : day);
123
+ }
124
+ /** The local time, split up. WDAY counts from 1 for Monday to 7 for Sunday, as ISO 8601 does */
125
+ class ClockBlock {
126
+ TOD = 0;
127
+ HOUR = 0;
128
+ MIN = 0;
129
+ WDAY = 1;
130
+ DAY = 1;
131
+ MONTH = 1;
132
+ YEAR = 1970;
133
+ run(now = Date.now()) {
134
+ const date = new Date(now);
135
+ this.TOD = timeOfDay(now);
136
+ this.HOUR = date.getHours();
137
+ this.MIN = date.getMinutes();
138
+ this.WDAY = date.getDay() || 7;
139
+ this.DAY = date.getDate();
140
+ this.MONTH = date.getMonth() + 1;
141
+ this.YEAR = date.getFullYear();
142
+ }
143
+ }
144
+ exports.ClockBlock = ClockBlock;
145
+ /**
146
+ * SCHEDULE: Q is true for one cycle when the time of its cron pattern comes. The runtime watches the
147
+ * time (`rt.cron()`) and counts the times that came; a cycle takes them.
148
+ */
149
+ class ScheduleBlock {
150
+ Q = false;
151
+ /** Times that came since the last cycle */
152
+ pending = 0;
153
+ run() {
154
+ this.Q = this.pending > 0;
155
+ this.pending = 0;
156
+ }
157
+ }
158
+ exports.ScheduleBlock = ScheduleBlock;
159
+ // ---- blocks with a state
160
+ /** Set/reset flip-flop, reset dominant */
161
+ class RsBlock {
162
+ Q1 = false;
163
+ run(S, R1) {
164
+ this.Q1 = !R1 && (S || this.Q1);
165
+ }
166
+ }
167
+ exports.RsBlock = RsBlock;
168
+ /** Set/reset flip-flop, set dominant */
169
+ class SrBlock {
170
+ Q1 = false;
171
+ run(S1, R) {
172
+ this.Q1 = S1 || (!R && this.Q1);
173
+ }
174
+ }
175
+ exports.SrBlock = SrBlock;
176
+ /**
177
+ * Rising edge. In the first cycle an input that is already true is not an edge - it was true
178
+ * before the script started.
179
+ */
180
+ class RTrigBlock {
181
+ Q = false;
182
+ last = false;
183
+ run(CLK, firstScan) {
184
+ this.Q = !firstScan && CLK && !this.last;
185
+ this.last = CLK;
186
+ }
187
+ }
188
+ exports.RTrigBlock = RTrigBlock;
189
+ /** Falling edge */
190
+ class FTrigBlock {
191
+ Q = false;
192
+ last = false;
193
+ run(CLK, firstScan) {
194
+ this.Q = !firstScan && !CLK && this.last;
195
+ this.last = CLK;
196
+ }
197
+ }
198
+ exports.FTrigBlock = FTrigBlock;
199
+ /*
200
+ * The timers count from the cycle that sees the edge, not from the one before: `dt` of that cycle
201
+ * is mostly time in which IN still had its old value. A cycle that runs early because an input
202
+ * changed would otherwise let the timer expire early - the time is never shorter than PT, at most
203
+ * one cycle longer, as in any SPS.
204
+ */
205
+ /** On delay: Q follows IN once IN was true for PT ms */
206
+ class TonBlock {
207
+ Q = false;
208
+ ET = 0;
209
+ last = false;
210
+ run(IN, PT, dt) {
211
+ if (IN) {
212
+ if (this.last) {
213
+ this.ET = Math.min(this.ET + dt, PT);
214
+ }
215
+ this.Q = this.ET >= PT;
216
+ }
217
+ else {
218
+ this.ET = 0;
219
+ this.Q = false;
220
+ }
221
+ this.last = IN;
222
+ }
223
+ }
224
+ exports.TonBlock = TonBlock;
225
+ /** Off delay: Q stays true for PT ms after IN went false */
226
+ class TofBlock {
227
+ Q = false;
228
+ ET = 0;
229
+ last = false;
230
+ run(IN, PT, dt) {
231
+ if (IN) {
232
+ this.ET = 0;
233
+ this.Q = true;
234
+ }
235
+ else if (this.Q) {
236
+ if (!this.last) {
237
+ this.ET = Math.min(this.ET + dt, PT);
238
+ }
239
+ this.Q = this.ET < PT;
240
+ }
241
+ this.last = IN;
242
+ }
243
+ }
244
+ exports.TofBlock = TofBlock;
245
+ /** Pulse: a rising edge of IN gives a pulse of PT ms, which cannot be retriggered */
246
+ class TpBlock {
247
+ Q = false;
248
+ ET = 0;
249
+ last = false;
250
+ run(IN, PT, dt) {
251
+ if (this.Q) {
252
+ this.ET = Math.min(this.ET + dt, PT);
253
+ if (this.ET >= PT) {
254
+ this.Q = false;
255
+ }
256
+ }
257
+ else if (IN && !this.last) {
258
+ this.Q = true;
259
+ this.ET = 0;
260
+ }
261
+ else if (!IN && this.ET >= PT) {
262
+ this.ET = 0;
263
+ }
264
+ this.last = IN;
265
+ }
266
+ }
267
+ exports.TpBlock = TpBlock;
268
+ // ---- control
269
+ /** Two-point switch: Q goes on when IN rises above HIGH and off when it falls below LOW */
270
+ class HystBlock {
271
+ Q = false;
272
+ run(IN, HIGH, LOW) {
273
+ if (IN > HIGH) {
274
+ this.Q = true;
275
+ }
276
+ else if (IN < LOW) {
277
+ this.Q = false;
278
+ }
279
+ }
280
+ }
281
+ exports.HystBlock = HystBlock;
282
+ /**
283
+ * OUT follows IN, but changes by at most UP per second upwards and DOWN per second downwards. A rate
284
+ * of 0 or less does not limit. It starts at IN, not at 0.
285
+ */
286
+ class RampBlock {
287
+ OUT = 0;
288
+ run(IN, UP, DOWN, dt, firstScan) {
289
+ if (firstScan) {
290
+ this.OUT = IN;
291
+ }
292
+ else if (IN > this.OUT) {
293
+ this.OUT = UP > 0 ? Math.min(IN, this.OUT + (UP * dt) / 1000) : IN;
294
+ }
295
+ else if (IN < this.OUT) {
296
+ this.OUT = DOWN > 0 ? Math.max(IN, this.OUT - (DOWN * dt) / 1000) : IN;
297
+ }
298
+ }
299
+ }
300
+ exports.RampBlock = RampBlock;
301
+ /**
302
+ * Low pass of the first order (PT1) with the time constant T in ms. Computed with the exponential, so
303
+ * the result does not depend on how the time is cut into cycles. It starts at IN.
304
+ */
305
+ class Pt1Block {
306
+ OUT = 0;
307
+ run(IN, T, dt, firstScan) {
308
+ if (firstScan || T <= 0) {
309
+ this.OUT = IN;
310
+ }
311
+ else {
312
+ this.OUT += (IN - this.OUT) * (1 - Math.exp(-dt / T));
313
+ }
314
+ }
315
+ }
316
+ exports.Pt1Block = Pt1Block;
317
+ /**
318
+ * PID controller in the form Y = KP * (e + 1/TN * ∫e dt + TV * de/dt), with e = SP - PV and TN, TV in
319
+ * ms; TN or TV of 0 leaves that part out.
320
+ *
321
+ * - The derivative is taken from PV and not from e, so a new set point gives no kick. It is smoothed
322
+ * with a tenth of TV - a cycle that comes early because an input changed has a small `dt`, which
323
+ * would make it jump.
324
+ * - Anti-windup: while Y is at a limit, the integral part does not grow further in that direction.
325
+ * - RST clears the integral part and holds Y at the P part.
326
+ */
327
+ class PidBlock {
328
+ Y = 0;
329
+ integral = 0;
330
+ derivative = 0;
331
+ lastPV = 0;
332
+ run(SP, PV, KP, TN, TV, YMIN, YMAX, RST, dt, firstScan) {
333
+ const low = Math.min(YMIN, YMAX);
334
+ const high = Math.max(YMIN, YMAX);
335
+ const error = SP - PV;
336
+ const proportional = KP * error;
337
+ if (firstScan || RST) {
338
+ this.integral = 0;
339
+ this.derivative = 0;
340
+ }
341
+ else if (dt > 0) {
342
+ if (TV > 0) {
343
+ const raw = (-KP * TV * (PV - this.lastPV)) / dt;
344
+ this.derivative += (raw - this.derivative) * (1 - Math.exp(-dt / (TV / 10)));
345
+ }
346
+ else {
347
+ this.derivative = 0;
348
+ }
349
+ if (TN > 0) {
350
+ // anti-windup: the integral part grows up to where Y reaches a limit, not beyond
351
+ const next = this.integral + (KP * error * dt) / TN;
352
+ const rest = proportional + this.derivative;
353
+ if (next > this.integral) {
354
+ this.integral = Math.min(next, Math.max(this.integral, high - rest));
355
+ }
356
+ else {
357
+ this.integral = Math.max(next, Math.min(this.integral, low - rest));
358
+ }
359
+ }
360
+ else {
361
+ this.integral = 0;
362
+ }
363
+ }
364
+ this.lastPV = PV;
365
+ this.Y = Math.min(high, Math.max(low, proportional + this.integral + this.derivative));
366
+ }
367
+ }
368
+ exports.PidBlock = PidBlock;
369
+ // ---- counters
370
+ /*
371
+ * The counters count rising edges. In the first cycle an input that is already true is no edge, as
372
+ * with R_TRIG - it was true before the script started.
373
+ */
374
+ /** Counts up on CU; R sets CV back to 0. Q: CV reached PV */
375
+ class CtuBlock {
376
+ Q = false;
377
+ CV = 0;
378
+ last = false;
379
+ run(CU, R, PV, firstScan) {
380
+ if (R) {
381
+ this.CV = 0;
382
+ }
383
+ else if (CU && !this.last && !firstScan) {
384
+ this.CV++;
385
+ }
386
+ this.last = CU;
387
+ this.Q = this.CV >= PV;
388
+ }
389
+ }
390
+ exports.CtuBlock = CtuBlock;
391
+ /** Counts down on CD; LD loads PV. Q: CV reached 0 */
392
+ class CtdBlock {
393
+ Q = true;
394
+ CV = 0;
395
+ last = false;
396
+ run(CD, LD, PV, firstScan) {
397
+ if (LD) {
398
+ this.CV = PV;
399
+ }
400
+ else if (CD && !this.last && !firstScan) {
401
+ this.CV--;
402
+ }
403
+ this.last = CD;
404
+ this.Q = this.CV <= 0;
405
+ }
406
+ }
407
+ exports.CtdBlock = CtdBlock;
408
+ /** Counts up on CU and down on CD; R sets 0 and goes before LD, which loads PV */
409
+ class CtudBlock {
410
+ QU = false;
411
+ QD = true;
412
+ CV = 0;
413
+ lastUp = false;
414
+ lastDown = false;
415
+ run(CU, CD, R, LD, PV, firstScan) {
416
+ if (R) {
417
+ this.CV = 0;
418
+ }
419
+ else if (LD) {
420
+ this.CV = PV;
421
+ }
422
+ else if (!firstScan) {
423
+ const up = CU && !this.lastUp;
424
+ const down = CD && !this.lastDown;
425
+ // both at once cancel each other out
426
+ if (up && !down) {
427
+ this.CV++;
428
+ }
429
+ else if (down && !up) {
430
+ this.CV--;
431
+ }
432
+ }
433
+ this.lastUp = CU;
434
+ this.lastDown = CD;
435
+ this.QU = this.CV >= PV;
436
+ this.QD = this.CV <= 0;
437
+ }
438
+ }
439
+ exports.CtudBlock = CtudBlock;
440
+ /**
441
+ * Blinker: while EN is true, Q is true for TH ms and false for TL ms, beginning with true. A cycle
442
+ * longer than both together skips the periods it missed - Q is where it would be.
443
+ */
444
+ class BlinkBlock {
445
+ Q = false;
446
+ /** Time in the current phase */
447
+ elapsed = 0;
448
+ running = false;
449
+ run(EN, TH, TL, dt) {
450
+ if (!EN) {
451
+ this.Q = false;
452
+ this.running = false;
453
+ return;
454
+ }
455
+ if (!this.running) {
456
+ this.running = true;
457
+ this.Q = true;
458
+ this.elapsed = 0;
459
+ return;
460
+ }
461
+ this.elapsed += dt;
462
+ const period = TH + TL;
463
+ if (period > 0 && this.elapsed >= period) {
464
+ this.elapsed %= period;
465
+ }
466
+ // with the rest of a period left, at most one phase ends; with a period of 0, Q turns every cycle
467
+ const phase = this.Q ? TH : TL;
468
+ if (this.elapsed >= phase) {
469
+ this.elapsed -= phase;
470
+ this.Q = !this.Q;
471
+ }
472
+ }
473
+ }
474
+ exports.BlinkBlock = BlinkBlock;
475
+ // ---- messages
476
+ /** Lines a LOG block writes at most within a minute */
477
+ exports.LOG_LIMIT = 20;
478
+ /** Messages a NOTIFY or SENDTO block sends at most within a minute - they reach people */
479
+ exports.MESSAGE_LIMIT = 5;
480
+ const MESSAGE_WINDOW_MS = 60000;
481
+ /**
482
+ * A line for the log or a message: on a rising edge of TRIG (`when` = `edge`), or whenever IN changes
483
+ * (`change`). `%s` in the text is the value of IN. Not in the first cycle - neither an edge nor a
484
+ * change is known then.
485
+ *
486
+ * At most `limit` within a minute: a diagram that runs every 200 ms would flood the log or a phone
487
+ * otherwise. The last one that may go says so. The minute counts the time of the cycles.
488
+ */
489
+ class MessageBlock {
490
+ limit;
491
+ noun;
492
+ /** The text of this cycle; valid when `run()` gave true */
493
+ text = '';
494
+ /** The text is the last one of this minute */
495
+ last = false;
496
+ lastTrig = false;
497
+ lastValue = undefined;
498
+ window = 0;
499
+ count = 0;
500
+ constructor(limit,
501
+ /** What it makes, for the note: `lines` or `messages` */
502
+ noun = 'lines') {
503
+ this.limit = limit;
504
+ this.noun = noun;
505
+ }
506
+ /** The text for the log, with the note when it is the last one of the minute */
507
+ get line() {
508
+ return this.last ? `${this.text} (${this.note()})` : this.text;
509
+ }
510
+ /** Why nothing comes for the rest of the minute */
511
+ note() {
512
+ return `${this.limit} ${this.noun} a minute at most - more are left out until the minute is over`;
513
+ }
514
+ run(TRIG, IN, text, when, dt, firstScan) {
515
+ this.window += dt;
516
+ if (this.window >= MESSAGE_WINDOW_MS) {
517
+ this.window = 0;
518
+ this.count = 0;
519
+ }
520
+ const fire = !firstScan && (when === 'change' ? !Object.is(IN, this.lastValue) : TRIG && !this.lastTrig);
521
+ this.lastTrig = TRIG;
522
+ this.lastValue = IN;
523
+ if (!fire || this.count >= this.limit) {
524
+ return false;
525
+ }
526
+ this.count++;
527
+ this.text = text.includes('%s')
528
+ ? text.split('%s').join(IN === undefined || IN === null ? String(IN) : toStr(IN))
529
+ : text;
530
+ this.last = this.count === this.limit;
531
+ return true;
532
+ }
533
+ }
534
+ exports.MessageBlock = MessageBlock;
535
+ /**
536
+ * A block with code of the user. The function gets the inputs, `dt`, `firstScan` and `state` - an
537
+ * object that is kept from one cycle to the next. It returns the value of OUT1, or an array with the
538
+ * values of OUT1, OUT2, ... Where it gives `undefined`, an output keeps its value.
539
+ */
540
+ class JsBlock {
541
+ fn;
542
+ /** The outputs, OUT1 at 0 - they start at 0, as the signals do */
543
+ out;
544
+ state = {};
545
+ constructor(fn, outputs = 1) {
546
+ this.fn = fn;
547
+ this.out = new Array(outputs).fill(0);
548
+ }
549
+ run(inputs, dt, firstScan) {
550
+ const result = this.fn(...inputs, dt, firstScan, this.state);
551
+ const values = Array.isArray(result) ? result : [result];
552
+ values.forEach((value, i) => {
553
+ if (value !== undefined) {
554
+ // more values than outputs are left out
555
+ if (i < this.out.length) {
556
+ this.out[i] = value;
557
+ }
558
+ }
559
+ });
560
+ }
561
+ }
562
+ exports.JsBlock = JsBlock;
563
+ const RS = () => new RsBlock();
564
+ exports.RS = RS;
565
+ const SR = () => new SrBlock();
566
+ exports.SR = SR;
567
+ const R_TRIG = () => new RTrigBlock();
568
+ exports.R_TRIG = R_TRIG;
569
+ const F_TRIG = () => new FTrigBlock();
570
+ exports.F_TRIG = F_TRIG;
571
+ const TON = () => new TonBlock();
572
+ exports.TON = TON;
573
+ const TOF = () => new TofBlock();
574
+ exports.TOF = TOF;
575
+ const TP = () => new TpBlock();
576
+ exports.TP = TP;
577
+ const HYST = () => new HystBlock();
578
+ exports.HYST = HYST;
579
+ const RAMP = () => new RampBlock();
580
+ exports.RAMP = RAMP;
581
+ const PT1 = () => new Pt1Block();
582
+ exports.PT1 = PT1;
583
+ const PID = () => new PidBlock();
584
+ exports.PID = PID;
585
+ const LOG = () => new MessageBlock(exports.LOG_LIMIT);
586
+ exports.LOG = LOG;
587
+ const NOTIFY = () => new MessageBlock(exports.MESSAGE_LIMIT, 'messages');
588
+ exports.NOTIFY = NOTIFY;
589
+ const SENDTO = () => new MessageBlock(exports.MESSAGE_LIMIT, 'messages');
590
+ exports.SENDTO = SENDTO;
591
+ const CLOCK = () => new ClockBlock();
592
+ exports.CLOCK = CLOCK;
593
+ const SCHEDULE = () => new ScheduleBlock();
594
+ exports.SCHEDULE = SCHEDULE;
595
+ const CTU = () => new CtuBlock();
596
+ exports.CTU = CTU;
597
+ const CTD = () => new CtdBlock();
598
+ exports.CTD = CTD;
599
+ const CTUD = () => new CtudBlock();
600
+ exports.CTUD = CTUD;
601
+ const BLINK = () => new BlinkBlock();
602
+ exports.BLINK = BLINK;
603
+ const JS = (fn, outputs) => new JsBlock(fn, outputs);
604
+ exports.JS = JS;
605
+ //# sourceMappingURL=blocks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blocks.js","sourceRoot":"","sources":["../../../src/lib/fb/blocks.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The blocks of the library that remember something, and the conversions of the generated code.\n *\n * Pure code without Node or the DOM: fb-runtime hands them to the generated code, and the editor\n * runs the same classes for the preview of a block - so the two never tell different stories.\n */\n\nimport { parseTime } from './time';\n\n// ---- conversions\n\nexport function toBool(value: unknown): boolean {\n if (typeof value === 'string') {\n const text = value.trim().toLowerCase();\n return text === 'true' || text === 'on' || text === '1' || text === 'yes';\n }\n return !!value;\n}\n\nexport function toNum(value: unknown): number {\n if (typeof value === 'boolean') {\n return value ? 1 : 0;\n }\n const number = typeof value === 'number' ? value : parseFloat(String(value));\n return Number.isFinite(number) ? number : NaN;\n}\n\n/** A division that gives 0 instead of Infinity or NaN for a divisor of 0 */\nexport function div(a: number, b: number): number {\n return b ? a / b : 0;\n}\n\n/** A number of TO_REAL: a decimal comma counts as a point, what is no number gives 0 */\nexport function toReal(value: unknown): number {\n const number = toNum(typeof value === 'string' ? value.replace(',', '.') : value);\n return Number.isNaN(number) ? 0 : number;\n}\n\n/** A whole number of TO_INT: rounded, as REAL_TO_INT of IEC does */\nexport function toInt(value: unknown): number {\n return Math.round(toReal(value));\n}\n\n/** A time of TO_TIME: a number is ms, a text may be `2s` or `08:30` as well; what is no time gives 0 */\nexport function toTime(value: unknown): number {\n if (typeof value === 'string') {\n return parseTime(value) ?? parseTime(toReal(value)) ?? 0;\n }\n return parseTime(toReal(value)) ?? 0;\n}\n\n/** A value as text: numbers and booleans as with String(), objects as JSON */\nexport function toStr(value: unknown): string {\n switch (typeof value) {\n case 'string':\n return value;\n case 'number':\n case 'boolean':\n return value.toString();\n case 'undefined':\n return '';\n default:\n return value === null ? '' : JSON.stringify(value);\n }\n}\n\n/** All inputs of CONCAT as one text */\nexport function concat(...values: unknown[]): string {\n return values.map(toStr).join('');\n}\n\n/**\n * Rounded to `digits` decimals, 0 to 10. Through the exponent of the text, so `1.005` gives `1.01`\n * and not `1` as `Math.round(1.005 * 100) / 100` would.\n */\nexport function round(value: number, digits: number): number {\n const places = Math.max(0, Math.min(10, Math.round(digits) || 0));\n if (!Number.isFinite(value)) {\n return 0;\n }\n const rounded = Number(`${Math.round(Number(`${value}e${places}`))}e-${places}`);\n // a number that is written with an exponent already, like 1e-7, does not take one more\n return Number.isFinite(rounded) ? rounded : Math.round(value * 10 ** places) / 10 ** places;\n}\n\n// ---- time of day\n\n/** The time of day in ms since the local midnight */\nexport function timeOfDay(now = Date.now()): number {\n const date = new Date(now);\n return ((date.getHours() * 60 + date.getMinutes()) * 60 + date.getSeconds()) * 1000 + date.getMilliseconds();\n}\n\n/**\n * Whether a time of day lies in the window from `start` to `end` - including the start, not the\n * end. A window with `start` after `end` goes over midnight; `start` equal to `end` is empty.\n */\nexport function inWindow(time: number, start: number, end: number): boolean {\n return start <= end ? time >= start && time < end : time >= start || time < end;\n}\n\n/** Days of TIMEWINDOW */\nconst DAYS: Record<string, (day: number) => boolean> = {\n all: () => true,\n // getDay(): 0 is Sunday\n weekdays: day => day >= 1 && day <= 5,\n weekend: day => day === 0 || day === 6,\n};\n\n/**\n * TIMEWINDOW: whether now is between `start` and `end` on the days `days` (`all`, `weekdays`,\n * `weekend`). A window over midnight belongs to the day it starts on: Friday 22:00 to 06:00 lasts\n * until Saturday 06:00, and Monday 00:00 to 06:00 belongs to Sunday.\n */\nexport function timeWindow(start: number, end: number, days: string, now = Date.now()): boolean {\n const time = timeOfDay(now);\n if (!inWindow(time, start, end)) {\n return false;\n }\n const day = new Date(now).getDay();\n const isDay = DAYS[days] || DAYS.all;\n // after midnight in a window that started the day before\n return isDay(start > end && time < end ? (day + 6) % 7 : day);\n}\n\n/** The local time, split up. WDAY counts from 1 for Monday to 7 for Sunday, as ISO 8601 does */\nexport class ClockBlock {\n TOD = 0;\n HOUR = 0;\n MIN = 0;\n WDAY = 1;\n DAY = 1;\n MONTH = 1;\n YEAR = 1970;\n run(now = Date.now()): void {\n const date = new Date(now);\n this.TOD = timeOfDay(now);\n this.HOUR = date.getHours();\n this.MIN = date.getMinutes();\n this.WDAY = date.getDay() || 7;\n this.DAY = date.getDate();\n this.MONTH = date.getMonth() + 1;\n this.YEAR = date.getFullYear();\n }\n}\n\n/**\n * SCHEDULE: Q is true for one cycle when the time of its cron pattern comes. The runtime watches the\n * time (`rt.cron()`) and counts the times that came; a cycle takes them.\n */\nexport class ScheduleBlock {\n Q = false;\n /** Times that came since the last cycle */\n pending = 0;\n run(): void {\n this.Q = this.pending > 0;\n this.pending = 0;\n }\n}\n\n// ---- blocks with a state\n\n/** Set/reset flip-flop, reset dominant */\nexport class RsBlock {\n Q1 = false;\n run(S: boolean, R1: boolean): void {\n this.Q1 = !R1 && (S || this.Q1);\n }\n}\n\n/** Set/reset flip-flop, set dominant */\nexport class SrBlock {\n Q1 = false;\n run(S1: boolean, R: boolean): void {\n this.Q1 = S1 || (!R && this.Q1);\n }\n}\n\n/**\n * Rising edge. In the first cycle an input that is already true is not an edge - it was true\n * before the script started.\n */\nexport class RTrigBlock {\n Q = false;\n private last = false;\n run(CLK: boolean, firstScan: boolean): void {\n this.Q = !firstScan && CLK && !this.last;\n this.last = CLK;\n }\n}\n\n/** Falling edge */\nexport class FTrigBlock {\n Q = false;\n private last = false;\n run(CLK: boolean, firstScan: boolean): void {\n this.Q = !firstScan && !CLK && this.last;\n this.last = CLK;\n }\n}\n\n/*\n * The timers count from the cycle that sees the edge, not from the one before: `dt` of that cycle\n * is mostly time in which IN still had its old value. A cycle that runs early because an input\n * changed would otherwise let the timer expire early - the time is never shorter than PT, at most\n * one cycle longer, as in any SPS.\n */\n\n/** On delay: Q follows IN once IN was true for PT ms */\nexport class TonBlock {\n Q = false;\n ET = 0;\n private last = false;\n run(IN: boolean, PT: number, dt: number): void {\n if (IN) {\n if (this.last) {\n this.ET = Math.min(this.ET + dt, PT);\n }\n this.Q = this.ET >= PT;\n } else {\n this.ET = 0;\n this.Q = false;\n }\n this.last = IN;\n }\n}\n\n/** Off delay: Q stays true for PT ms after IN went false */\nexport class TofBlock {\n Q = false;\n ET = 0;\n private last = false;\n run(IN: boolean, PT: number, dt: number): void {\n if (IN) {\n this.ET = 0;\n this.Q = true;\n } else if (this.Q) {\n if (!this.last) {\n this.ET = Math.min(this.ET + dt, PT);\n }\n this.Q = this.ET < PT;\n }\n this.last = IN;\n }\n}\n\n/** Pulse: a rising edge of IN gives a pulse of PT ms, which cannot be retriggered */\nexport class TpBlock {\n Q = false;\n ET = 0;\n private last = false;\n run(IN: boolean, PT: number, dt: number): void {\n if (this.Q) {\n this.ET = Math.min(this.ET + dt, PT);\n if (this.ET >= PT) {\n this.Q = false;\n }\n } else if (IN && !this.last) {\n this.Q = true;\n this.ET = 0;\n } else if (!IN && this.ET >= PT) {\n this.ET = 0;\n }\n this.last = IN;\n }\n}\n\n// ---- control\n\n/** Two-point switch: Q goes on when IN rises above HIGH and off when it falls below LOW */\nexport class HystBlock {\n Q = false;\n run(IN: number, HIGH: number, LOW: number): void {\n if (IN > HIGH) {\n this.Q = true;\n } else if (IN < LOW) {\n this.Q = false;\n }\n }\n}\n\n/**\n * OUT follows IN, but changes by at most UP per second upwards and DOWN per second downwards. A rate\n * of 0 or less does not limit. It starts at IN, not at 0.\n */\nexport class RampBlock {\n OUT = 0;\n run(IN: number, UP: number, DOWN: number, dt: number, firstScan: boolean): void {\n if (firstScan) {\n this.OUT = IN;\n } else if (IN > this.OUT) {\n this.OUT = UP > 0 ? Math.min(IN, this.OUT + (UP * dt) / 1000) : IN;\n } else if (IN < this.OUT) {\n this.OUT = DOWN > 0 ? Math.max(IN, this.OUT - (DOWN * dt) / 1000) : IN;\n }\n }\n}\n\n/**\n * Low pass of the first order (PT1) with the time constant T in ms. Computed with the exponential, so\n * the result does not depend on how the time is cut into cycles. It starts at IN.\n */\nexport class Pt1Block {\n OUT = 0;\n run(IN: number, T: number, dt: number, firstScan: boolean): void {\n if (firstScan || T <= 0) {\n this.OUT = IN;\n } else {\n this.OUT += (IN - this.OUT) * (1 - Math.exp(-dt / T));\n }\n }\n}\n\n/**\n * PID controller in the form Y = KP * (e + 1/TN * ∫e dt + TV * de/dt), with e = SP - PV and TN, TV in\n * ms; TN or TV of 0 leaves that part out.\n *\n * - The derivative is taken from PV and not from e, so a new set point gives no kick. It is smoothed\n * with a tenth of TV - a cycle that comes early because an input changed has a small `dt`, which\n * would make it jump.\n * - Anti-windup: while Y is at a limit, the integral part does not grow further in that direction.\n * - RST clears the integral part and holds Y at the P part.\n */\nexport class PidBlock {\n Y = 0;\n private integral = 0;\n private derivative = 0;\n private lastPV = 0;\n run(\n SP: number,\n PV: number,\n KP: number,\n TN: number,\n TV: number,\n YMIN: number,\n YMAX: number,\n RST: boolean,\n dt: number,\n firstScan: boolean,\n ): void {\n const low = Math.min(YMIN, YMAX);\n const high = Math.max(YMIN, YMAX);\n const error = SP - PV;\n const proportional = KP * error;\n\n if (firstScan || RST) {\n this.integral = 0;\n this.derivative = 0;\n } else if (dt > 0) {\n if (TV > 0) {\n const raw = (-KP * TV * (PV - this.lastPV)) / dt;\n this.derivative += (raw - this.derivative) * (1 - Math.exp(-dt / (TV / 10)));\n } else {\n this.derivative = 0;\n }\n if (TN > 0) {\n // anti-windup: the integral part grows up to where Y reaches a limit, not beyond\n const next = this.integral + (KP * error * dt) / TN;\n const rest = proportional + this.derivative;\n if (next > this.integral) {\n this.integral = Math.min(next, Math.max(this.integral, high - rest));\n } else {\n this.integral = Math.max(next, Math.min(this.integral, low - rest));\n }\n } else {\n this.integral = 0;\n }\n }\n this.lastPV = PV;\n this.Y = Math.min(high, Math.max(low, proportional + this.integral + this.derivative));\n }\n}\n\n// ---- counters\n\n/*\n * The counters count rising edges. In the first cycle an input that is already true is no edge, as\n * with R_TRIG - it was true before the script started.\n */\n\n/** Counts up on CU; R sets CV back to 0. Q: CV reached PV */\nexport class CtuBlock {\n Q = false;\n CV = 0;\n private last = false;\n run(CU: boolean, R: boolean, PV: number, firstScan: boolean): void {\n if (R) {\n this.CV = 0;\n } else if (CU && !this.last && !firstScan) {\n this.CV++;\n }\n this.last = CU;\n this.Q = this.CV >= PV;\n }\n}\n\n/** Counts down on CD; LD loads PV. Q: CV reached 0 */\nexport class CtdBlock {\n Q = true;\n CV = 0;\n private last = false;\n run(CD: boolean, LD: boolean, PV: number, firstScan: boolean): void {\n if (LD) {\n this.CV = PV;\n } else if (CD && !this.last && !firstScan) {\n this.CV--;\n }\n this.last = CD;\n this.Q = this.CV <= 0;\n }\n}\n\n/** Counts up on CU and down on CD; R sets 0 and goes before LD, which loads PV */\nexport class CtudBlock {\n QU = false;\n QD = true;\n CV = 0;\n private lastUp = false;\n private lastDown = false;\n run(CU: boolean, CD: boolean, R: boolean, LD: boolean, PV: number, firstScan: boolean): void {\n if (R) {\n this.CV = 0;\n } else if (LD) {\n this.CV = PV;\n } else if (!firstScan) {\n const up = CU && !this.lastUp;\n const down = CD && !this.lastDown;\n // both at once cancel each other out\n if (up && !down) {\n this.CV++;\n } else if (down && !up) {\n this.CV--;\n }\n }\n this.lastUp = CU;\n this.lastDown = CD;\n this.QU = this.CV >= PV;\n this.QD = this.CV <= 0;\n }\n}\n\n/**\n * Blinker: while EN is true, Q is true for TH ms and false for TL ms, beginning with true. A cycle\n * longer than both together skips the periods it missed - Q is where it would be.\n */\nexport class BlinkBlock {\n Q = false;\n /** Time in the current phase */\n private elapsed = 0;\n private running = false;\n run(EN: boolean, TH: number, TL: number, dt: number): void {\n if (!EN) {\n this.Q = false;\n this.running = false;\n return;\n }\n if (!this.running) {\n this.running = true;\n this.Q = true;\n this.elapsed = 0;\n return;\n }\n this.elapsed += dt;\n const period = TH + TL;\n if (period > 0 && this.elapsed >= period) {\n this.elapsed %= period;\n }\n // with the rest of a period left, at most one phase ends; with a period of 0, Q turns every cycle\n const phase = this.Q ? TH : TL;\n if (this.elapsed >= phase) {\n this.elapsed -= phase;\n this.Q = !this.Q;\n }\n }\n}\n\n// ---- messages\n\n/** Lines a LOG block writes at most within a minute */\nexport const LOG_LIMIT = 20;\n/** Messages a NOTIFY or SENDTO block sends at most within a minute - they reach people */\nexport const MESSAGE_LIMIT = 5;\nconst MESSAGE_WINDOW_MS = 60000;\n\n/**\n * A line for the log or a message: on a rising edge of TRIG (`when` = `edge`), or whenever IN changes\n * (`change`). `%s` in the text is the value of IN. Not in the first cycle - neither an edge nor a\n * change is known then.\n *\n * At most `limit` within a minute: a diagram that runs every 200 ms would flood the log or a phone\n * otherwise. The last one that may go says so. The minute counts the time of the cycles.\n */\nexport class MessageBlock {\n /** The text of this cycle; valid when `run()` gave true */\n text = '';\n /** The text is the last one of this minute */\n last = false;\n private lastTrig = false;\n private lastValue: unknown = undefined;\n private window = 0;\n private count = 0;\n\n constructor(\n readonly limit: number,\n /** What it makes, for the note: `lines` or `messages` */\n private readonly noun = 'lines',\n ) {}\n\n /** The text for the log, with the note when it is the last one of the minute */\n get line(): string {\n return this.last ? `${this.text} (${this.note()})` : this.text;\n }\n\n /** Why nothing comes for the rest of the minute */\n note(): string {\n return `${this.limit} ${this.noun} a minute at most - more are left out until the minute is over`;\n }\n\n run(TRIG: boolean, IN: unknown, text: string, when: string, dt: number, firstScan: boolean): boolean {\n this.window += dt;\n if (this.window >= MESSAGE_WINDOW_MS) {\n this.window = 0;\n this.count = 0;\n }\n const fire = !firstScan && (when === 'change' ? !Object.is(IN, this.lastValue) : TRIG && !this.lastTrig);\n this.lastTrig = TRIG;\n this.lastValue = IN;\n if (!fire || this.count >= this.limit) {\n return false;\n }\n this.count++;\n this.text = text.includes('%s')\n ? text.split('%s').join(IN === undefined || IN === null ? String(IN) : toStr(IN))\n : text;\n this.last = this.count === this.limit;\n return true;\n }\n}\n\n// ---- expert\n\n/** The function of a JS block: its inputs, then `dt`, `firstScan` and `state` */\nexport type JsFunction = (...args: unknown[]) => unknown;\n\n/**\n * A block with code of the user. The function gets the inputs, `dt`, `firstScan` and `state` - an\n * object that is kept from one cycle to the next. It returns the value of OUT1, or an array with the\n * values of OUT1, OUT2, ... Where it gives `undefined`, an output keeps its value.\n */\nexport class JsBlock {\n /** The outputs, OUT1 at 0 - they start at 0, as the signals do */\n readonly out: unknown[];\n readonly state: Record<string, unknown> = {};\n\n constructor(\n private readonly fn: JsFunction,\n outputs = 1,\n ) {\n this.out = new Array(outputs).fill(0);\n }\n\n run(inputs: unknown[], dt: number, firstScan: boolean): void {\n const result = this.fn(...inputs, dt, firstScan, this.state);\n const values = Array.isArray(result) ? result : [result];\n values.forEach((value, i) => {\n if (value !== undefined) {\n // more values than outputs are left out\n if (i < this.out.length) {\n this.out[i] = value;\n }\n }\n });\n }\n}\n\nexport const RS = (): RsBlock => new RsBlock();\nexport const SR = (): SrBlock => new SrBlock();\nexport const R_TRIG = (): RTrigBlock => new RTrigBlock();\nexport const F_TRIG = (): FTrigBlock => new FTrigBlock();\nexport const TON = (): TonBlock => new TonBlock();\nexport const TOF = (): TofBlock => new TofBlock();\nexport const TP = (): TpBlock => new TpBlock();\nexport const HYST = (): HystBlock => new HystBlock();\nexport const RAMP = (): RampBlock => new RampBlock();\nexport const PT1 = (): Pt1Block => new Pt1Block();\nexport const PID = (): PidBlock => new PidBlock();\nexport const LOG = (): MessageBlock => new MessageBlock(LOG_LIMIT);\nexport const NOTIFY = (): MessageBlock => new MessageBlock(MESSAGE_LIMIT, 'messages');\nexport const SENDTO = (): MessageBlock => new MessageBlock(MESSAGE_LIMIT, 'messages');\nexport const CLOCK = (): ClockBlock => new ClockBlock();\nexport const SCHEDULE = (): ScheduleBlock => new ScheduleBlock();\nexport const CTU = (): CtuBlock => new CtuBlock();\nexport const CTD = (): CtdBlock => new CtdBlock();\nexport const CTUD = (): CtudBlock => new CtudBlock();\nexport const BLINK = (): BlinkBlock => new BlinkBlock();\nexport const JS = (fn: JsFunction, outputs?: number): JsBlock => new JsBlock(fn, outputs);\n"]}