iobroker.javascript 10.2.5 → 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 (114) hide show
  1. package/README.md +6 -14
  2. package/admin/assets/AiChatPanel-CpY4Bun-.js +27 -0
  3. package/admin/assets/{AiChatService-BOL3J2Jd.js → AiChatService-QKcpW4jQ.js} +1 -1
  4. package/admin/assets/AiDiffView-DscPfZ38.js +1 -0
  5. package/admin/assets/{AiInlineProvider-BIlcrTkS.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-DwHHsh9O.js → Debugger-teJTIU-2.js} +4 -4
  10. package/admin/assets/{Documentation-Bc0RmoEF.js → Documentation-uz4Ut9pT.js} +4 -4
  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-CEHpEFp7.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-CM95r358.js → _virtual_mf-localSharedImportMap___mfe_internal__iobroker_javascript__mf_owner__1-BnL93BgK.js} +1 -1
  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-BEpNZh4U.js → _virtual_mf___mfe_internal__iobroker_javascript__mf_owner__180366418666083__loadShare___mf_0_iobroker_mf_1_gui_mf_2_components__loadShare__.js-NI-3Uv4e.js} +75 -75
  22. package/admin/assets/{_virtual_mf___mfe_internal__iobroker_javascript__mf_owner__180366418666083__loadShare__react_mf_2_dom_mf_1_client__loadShare__.js-FeM77flT.js → _virtual_mf___mfe_internal__iobroker_javascript__mf_owner__180366418666083__loadShare__react_mf_2_dom_mf_1_client__loadShare__.js-DVaMIZyC.js} +1 -1
  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-BP2RjhQH.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-qIKzOAcV.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-CnmXLCUE.js → blocks_trigger-DeAYXpSS.js} +1 -1
  38. package/admin/assets/{cronHoverProvider-CcIFAhVy.js → cronHoverProvider-DoO2_tpG.js} +1 -1
  39. package/admin/assets/{field_cron-Ba46q8Qc.js → field_cron-D3Ts_s9M.js} +1 -1
  40. package/admin/assets/{field_oid-lWCjOzuq.js → field_oid-BRNXredg.js} +1 -1
  41. package/admin/assets/{field_script-BCWZHhnW.js → field_script-3X6ousg7.js} +1 -1
  42. package/admin/assets/helpers-BTGaTdnT.js +1 -0
  43. package/admin/assets/{hostInit-CVybS7BB.js → hostInit-2h2Cbsaw.js} +1 -1
  44. package/admin/assets/index-BHhhebRG.css +1 -0
  45. package/admin/assets/index-CbQlIKB_.js +156 -0
  46. package/admin/assets/{inlineChatWidget-N8xIkvxX.js → inlineChatWidget-BwQVCPkx.js} +2 -2
  47. package/admin/assets/{inlineDiffController-BuqYsKKq.js → inlineDiffController-BsDDsDHn.js} +2 -2
  48. package/admin/assets/loadBlocks-RpqM7PwO.js +117 -0
  49. package/admin/assets/loadMonaco-BVOEahNw.js +1 -0
  50. package/admin/assets/{mf-entry-bootstrap-0-a5a39621.js → mf-entry-bootstrap-0-0deef484.js} +3 -3
  51. package/admin/assets/{pendingShares-DOAkyFMS.js → pendingShares-BaAadIDv.js} +1 -1
  52. package/admin/assets/reactour.esm-DX9ZgYlx.js +137 -0
  53. package/admin/assets/{stateHoverProvider-BYAbe1Ay.js → stateHoverProvider-BEadnSXp.js} +1 -1
  54. package/admin/assets/tileFbd-CWAy7R7m.svg +85 -0
  55. package/admin/mf-manifest.json +1 -1
  56. package/admin/mf-stats.json +1 -1
  57. package/admin/remoteEntry.js +2 -2
  58. package/admin/tab.html +3 -7
  59. package/build/lib/fb/analyze.js +288 -0
  60. package/build/lib/fb/analyze.js.map +1 -0
  61. package/build/lib/fb/blocks.js +605 -0
  62. package/build/lib/fb/blocks.js.map +1 -0
  63. package/build/lib/fb/generate.js +326 -0
  64. package/build/lib/fb/generate.js.map +1 -0
  65. package/build/lib/fb/graph.js +240 -0
  66. package/build/lib/fb/graph.js.map +1 -0
  67. package/build/lib/fb/index.js +57 -0
  68. package/build/lib/fb/index.js.map +1 -0
  69. package/build/lib/fb/js.js +33 -0
  70. package/build/lib/fb/js.js.map +1 -0
  71. package/build/lib/fb/layout.js +205 -0
  72. package/build/lib/fb/layout.js.map +1 -0
  73. package/build/lib/fb/library.js +657 -0
  74. package/build/lib/fb/library.js.map +1 -0
  75. package/build/lib/fb/runtime.js +793 -0
  76. package/build/lib/fb/runtime.js.map +1 -0
  77. package/build/lib/fb/time.js +76 -0
  78. package/build/lib/fb/time.js.map +1 -0
  79. package/build/lib/fb/types.js +19 -0
  80. package/build/lib/fb/types.js.map +1 -0
  81. package/build/lib/fb/user.js +78 -0
  82. package/build/lib/fb/user.js.map +1 -0
  83. package/build/lib/javascript.d.ts +1 -1
  84. package/build/lib/mirror.js +4 -0
  85. package/build/lib/mirror.js.map +1 -1
  86. package/build/lib/sandbox.js +44 -0
  87. package/build/lib/sandbox.js.map +1 -1
  88. package/build/main.js +66 -1
  89. package/build/main.js.map +1 -1
  90. package/build/types.d.ts +9 -1
  91. package/docs/de/fbd.md +274 -0
  92. package/docs/en/fbd.md +260 -0
  93. package/io-package.json +39 -15
  94. package/package.json +1 -1
  95. package/admin/assets/AiChatPanel-oBeXbUFv.js +0 -27
  96. package/admin/assets/AiDiffView-C-KKjnJD.js +0 -1
  97. package/admin/assets/Error-DZ4vCykD.js +0 -1
  98. package/admin/assets/Import-Cu02ceLW.js +0 -1
  99. package/admin/assets/RulesEditor-QCbi1lV_.js +0 -1
  100. package/admin/assets/ScriptEditorVanillaMonaco-ChQmnk0p.js +0 -3
  101. package/admin/assets/aiPromptBuilder-DKler0UK.js +0 -1
  102. package/admin/assets/blocks_action-DywZVfRY.js +0 -1
  103. package/admin/assets/blocks_logic-CdTl5YZw.js +0 -1
  104. package/admin/assets/blocks_number-DXFd9Rva.js +0 -1
  105. package/admin/assets/blocks_object-by1uBDHi.js +0 -1
  106. package/admin/assets/blocks_procedures-BcJ7N70D.js +0 -3
  107. package/admin/assets/blocks_switch-dLF6hSJl.js +0 -2
  108. package/admin/assets/blocks_system-DmX-SBy8.js +0 -1
  109. package/admin/assets/blocks_text-BI4zNU3o.js +0 -1
  110. package/admin/assets/blocks_time-BgYA4Y_4.js +0 -1
  111. package/admin/assets/blocks_timeout-DUzgMyAu.js +0 -1
  112. package/admin/assets/helpers-CnEjYAup.js +0 -1
  113. package/admin/assets/index-B3s0zmWC.js +0 -871
  114. package/admin/assets/index-CXaeqPRy.css +0 -1
@@ -0,0 +1,657 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FB_CATEGORIES = exports.FB_LIBRARY = exports.FB_ASTRO_EVENTS = void 0;
4
+ exports.getTerminals = getTerminals;
5
+ exports.getBlockDef = getBlockDef;
6
+ /** The events of the sun ASTRO knows, in the order of a day - the names of `getAstroDate()` */
7
+ exports.FB_ASTRO_EVENTS = [
8
+ 'nightEnd',
9
+ 'nauticalDawn',
10
+ 'dawn',
11
+ 'sunrise',
12
+ 'sunriseEnd',
13
+ 'goldenHourEnd',
14
+ 'solarNoon',
15
+ 'goldenHour',
16
+ 'sunsetStart',
17
+ 'sunset',
18
+ 'dusk',
19
+ 'nauticalDusk',
20
+ 'night',
21
+ 'nadir',
22
+ ];
23
+ /**
24
+ * The blocks of the library: logic, memory (flip-flops, edges), timers, counters, comparison,
25
+ * arithmetic, conversion, control, calendar, messages, a block with code, and the ioBroker states.
26
+ *
27
+ * Type names follow IEC 61131-3. The editor translates the names of the categories, the types
28
+ * stay as they are - they are what SPS users look for.
29
+ */
30
+ exports.FB_LIBRARY = [
31
+ // ---- logic
32
+ {
33
+ type: 'AND',
34
+ category: 'logic',
35
+ inputs: [],
36
+ outputs: [{ id: 'OUT', type: 'BOOL' }],
37
+ // an open input of an AND must not block it
38
+ extensible: { prefix: 'IN', type: 'BOOL', default: true, min: 2, max: 16 },
39
+ code: '{OUT} = {IN*: && };',
40
+ },
41
+ {
42
+ type: 'OR',
43
+ category: 'logic',
44
+ inputs: [],
45
+ outputs: [{ id: 'OUT', type: 'BOOL' }],
46
+ extensible: { prefix: 'IN', type: 'BOOL', default: false, min: 2, max: 16 },
47
+ code: '{OUT} = {IN*: || };',
48
+ },
49
+ {
50
+ type: 'XOR',
51
+ category: 'logic',
52
+ inputs: [],
53
+ outputs: [{ id: 'OUT', type: 'BOOL' }],
54
+ // true for an odd number of true inputs, like a chain of XOR gates
55
+ extensible: { prefix: 'IN', type: 'BOOL', default: false, min: 2, max: 16 },
56
+ code: '{OUT} = {IN*: !== };',
57
+ },
58
+ {
59
+ type: 'NOT',
60
+ category: 'logic',
61
+ inputs: [{ id: 'IN', type: 'BOOL', default: false }],
62
+ outputs: [{ id: 'OUT', type: 'BOOL' }],
63
+ code: '{OUT} = !{IN};',
64
+ },
65
+ {
66
+ type: 'RS',
67
+ category: 'memory',
68
+ inputs: [
69
+ { id: 'S', type: 'BOOL', default: false },
70
+ { id: 'R1', type: 'BOOL', default: false },
71
+ ],
72
+ outputs: [{ id: 'Q1', type: 'BOOL' }],
73
+ stateful: true,
74
+ code: '{I}.run({S}, {R1}); {Q1} = {I}.Q1;',
75
+ },
76
+ {
77
+ type: 'SR',
78
+ category: 'memory',
79
+ inputs: [
80
+ { id: 'S1', type: 'BOOL', default: false },
81
+ { id: 'R', type: 'BOOL', default: false },
82
+ ],
83
+ outputs: [{ id: 'Q1', type: 'BOOL' }],
84
+ stateful: true,
85
+ code: '{I}.run({S1}, {R}); {Q1} = {I}.Q1;',
86
+ },
87
+ {
88
+ type: 'R_TRIG',
89
+ category: 'memory',
90
+ inputs: [{ id: 'CLK', type: 'BOOL', default: false }],
91
+ outputs: [{ id: 'Q', type: 'BOOL' }],
92
+ stateful: true,
93
+ code: '{I}.run({CLK}, firstScan); {Q} = {I}.Q;',
94
+ },
95
+ {
96
+ type: 'F_TRIG',
97
+ category: 'memory',
98
+ inputs: [{ id: 'CLK', type: 'BOOL', default: false }],
99
+ outputs: [{ id: 'Q', type: 'BOOL' }],
100
+ stateful: true,
101
+ code: '{I}.run({CLK}, firstScan); {Q} = {I}.Q;',
102
+ },
103
+ // ---- timers
104
+ {
105
+ type: 'TON',
106
+ category: 'timers',
107
+ inputs: [
108
+ { id: 'IN', type: 'BOOL', default: false },
109
+ { id: 'PT', type: 'TIME', param: true, default: 1000 },
110
+ ],
111
+ outputs: [
112
+ { id: 'Q', type: 'BOOL' },
113
+ { id: 'ET', type: 'TIME' },
114
+ ],
115
+ stateful: true,
116
+ timeDependent: true,
117
+ code: '{I}.run({IN}, {PT}, dt); {Q} = {I}.Q; {ET} = {I}.ET;',
118
+ },
119
+ {
120
+ type: 'TOF',
121
+ category: 'timers',
122
+ inputs: [
123
+ { id: 'IN', type: 'BOOL', default: false },
124
+ { id: 'PT', type: 'TIME', param: true, default: 1000 },
125
+ ],
126
+ outputs: [
127
+ { id: 'Q', type: 'BOOL' },
128
+ { id: 'ET', type: 'TIME' },
129
+ ],
130
+ stateful: true,
131
+ timeDependent: true,
132
+ code: '{I}.run({IN}, {PT}, dt); {Q} = {I}.Q; {ET} = {I}.ET;',
133
+ },
134
+ {
135
+ type: 'TP',
136
+ category: 'timers',
137
+ inputs: [
138
+ { id: 'IN', type: 'BOOL', default: false },
139
+ { id: 'PT', type: 'TIME', param: true, default: 1000 },
140
+ ],
141
+ outputs: [
142
+ { id: 'Q', type: 'BOOL' },
143
+ { id: 'ET', type: 'TIME' },
144
+ ],
145
+ stateful: true,
146
+ timeDependent: true,
147
+ code: '{I}.run({IN}, {PT}, dt); {Q} = {I}.Q; {ET} = {I}.ET;',
148
+ },
149
+ {
150
+ // blinker: TH ms on, TL ms off, while EN is true
151
+ type: 'BLINK',
152
+ category: 'timers',
153
+ inputs: [
154
+ { id: 'EN', type: 'BOOL', default: true },
155
+ { id: 'TH', type: 'TIME', param: true, default: 1000 },
156
+ { id: 'TL', type: 'TIME', param: true, default: 1000 },
157
+ ],
158
+ outputs: [{ id: 'Q', type: 'BOOL' }],
159
+ stateful: true,
160
+ timeDependent: true,
161
+ code: '{I}.run({EN}, {TH}, {TL}, dt); {Q} = {I}.Q;',
162
+ },
163
+ // ---- counters
164
+ {
165
+ type: 'CTU',
166
+ category: 'counters',
167
+ inputs: [
168
+ { id: 'CU', type: 'BOOL', default: false },
169
+ { id: 'R', type: 'BOOL', default: false },
170
+ { id: 'PV', type: 'INT', param: true, default: 10 },
171
+ ],
172
+ outputs: [
173
+ { id: 'Q', type: 'BOOL' },
174
+ { id: 'CV', type: 'INT' },
175
+ ],
176
+ stateful: true,
177
+ code: '{I}.run({CU}, {R}, {PV}, firstScan); {Q} = {I}.Q; {CV} = {I}.CV;',
178
+ },
179
+ {
180
+ type: 'CTD',
181
+ category: 'counters',
182
+ inputs: [
183
+ { id: 'CD', type: 'BOOL', default: false },
184
+ { id: 'LD', type: 'BOOL', default: false },
185
+ { id: 'PV', type: 'INT', param: true, default: 10 },
186
+ ],
187
+ outputs: [
188
+ { id: 'Q', type: 'BOOL' },
189
+ { id: 'CV', type: 'INT' },
190
+ ],
191
+ stateful: true,
192
+ code: '{I}.run({CD}, {LD}, {PV}, firstScan); {Q} = {I}.Q; {CV} = {I}.CV;',
193
+ },
194
+ {
195
+ type: 'CTUD',
196
+ category: 'counters',
197
+ inputs: [
198
+ { id: 'CU', type: 'BOOL', default: false },
199
+ { id: 'CD', type: 'BOOL', default: false },
200
+ { id: 'R', type: 'BOOL', default: false },
201
+ { id: 'LD', type: 'BOOL', default: false },
202
+ { id: 'PV', type: 'INT', param: true, default: 10 },
203
+ ],
204
+ outputs: [
205
+ { id: 'QU', type: 'BOOL' },
206
+ { id: 'QD', type: 'BOOL' },
207
+ { id: 'CV', type: 'INT' },
208
+ ],
209
+ stateful: true,
210
+ code: '{I}.run({CU}, {CD}, {R}, {LD}, {PV}, firstScan); {QU} = {I}.QU; {QD} = {I}.QD; {CV} = {I}.CV;',
211
+ },
212
+ // ---- comparison
213
+ ...[
214
+ ['GT', '>'],
215
+ ['GE', '>='],
216
+ ['LT', '<'],
217
+ ['LE', '<='],
218
+ ].map(([type, operator]) => ({
219
+ type,
220
+ category: 'compare',
221
+ inputs: [
222
+ { id: 'IN1', type: 'REAL', default: 0 },
223
+ { id: 'IN2', type: 'REAL', default: 0 },
224
+ ],
225
+ outputs: [{ id: 'OUT', type: 'BOOL' }],
226
+ code: `{OUT} = {IN1} ${operator} {IN2};`,
227
+ })),
228
+ ...[
229
+ ['EQ', '==='],
230
+ ['NE', '!=='],
231
+ ].map(([type, operator]) => ({
232
+ type,
233
+ category: 'compare',
234
+ inputs: [
235
+ { id: 'IN1', type: 'ANY', default: 0 },
236
+ { id: 'IN2', type: 'ANY', default: 0 },
237
+ ],
238
+ outputs: [{ id: 'OUT', type: 'BOOL' }],
239
+ code: `{OUT} = {IN1} ${operator} {IN2};`,
240
+ })),
241
+ // ---- arithmetic
242
+ {
243
+ type: 'ADD',
244
+ category: 'arithmetic',
245
+ inputs: [],
246
+ outputs: [{ id: 'OUT', type: 'REAL' }],
247
+ extensible: { prefix: 'IN', type: 'REAL', default: 0, min: 2, max: 16 },
248
+ code: '{OUT} = {IN*: + };',
249
+ },
250
+ {
251
+ type: 'MUL',
252
+ category: 'arithmetic',
253
+ inputs: [],
254
+ outputs: [{ id: 'OUT', type: 'REAL' }],
255
+ extensible: { prefix: 'IN', type: 'REAL', default: 1, min: 2, max: 16 },
256
+ code: '{OUT} = {IN*: * };',
257
+ },
258
+ {
259
+ type: 'SUB',
260
+ category: 'arithmetic',
261
+ inputs: [
262
+ { id: 'IN1', type: 'REAL', default: 0 },
263
+ { id: 'IN2', type: 'REAL', default: 0 },
264
+ ],
265
+ outputs: [{ id: 'OUT', type: 'REAL' }],
266
+ code: '{OUT} = {IN1} - {IN2};',
267
+ },
268
+ {
269
+ type: 'DIV',
270
+ category: 'arithmetic',
271
+ inputs: [
272
+ { id: 'IN1', type: 'REAL', default: 0 },
273
+ { id: 'IN2', type: 'REAL', default: 1 },
274
+ ],
275
+ outputs: [{ id: 'OUT', type: 'REAL' }],
276
+ // a division by zero gives 0 instead of Infinity, which no state could store
277
+ code: '{OUT} = fb.div({IN1}, {IN2});',
278
+ },
279
+ {
280
+ type: 'MIN',
281
+ category: 'arithmetic',
282
+ inputs: [],
283
+ outputs: [{ id: 'OUT', type: 'REAL' }],
284
+ extensible: { prefix: 'IN', type: 'REAL', default: 0, min: 2, max: 16 },
285
+ code: '{OUT} = Math.min({IN*:, });',
286
+ },
287
+ {
288
+ type: 'MAX',
289
+ category: 'arithmetic',
290
+ inputs: [],
291
+ outputs: [{ id: 'OUT', type: 'REAL' }],
292
+ extensible: { prefix: 'IN', type: 'REAL', default: 0, min: 2, max: 16 },
293
+ code: '{OUT} = Math.max({IN*:, });',
294
+ },
295
+ {
296
+ type: 'ROUND',
297
+ category: 'arithmetic',
298
+ inputs: [
299
+ { id: 'IN', type: 'REAL', default: 0 },
300
+ // decimals, 0 to 10
301
+ { id: 'DIGITS', type: 'INT', param: true, default: 0 },
302
+ ],
303
+ outputs: [{ id: 'OUT', type: 'REAL' }],
304
+ code: '{OUT} = fb.round({IN}, {DIGITS});',
305
+ },
306
+ // ---- conversion: from whatever comes in
307
+ ...[
308
+ ['TO_BOOL', 'BOOL', 'toBool'],
309
+ ['TO_INT', 'INT', 'toInt'],
310
+ ['TO_REAL', 'REAL', 'toReal'],
311
+ ['TO_TIME', 'TIME', 'toTime'],
312
+ ['TO_STRING', 'STRING', 'toStr'],
313
+ ].map(([type, output, convert]) => ({
314
+ type,
315
+ category: 'convert',
316
+ inputs: [{ id: 'IN', type: 'ANY', default: output === 'STRING' ? '' : 0 }],
317
+ outputs: [{ id: 'OUT', type: output }],
318
+ code: `{OUT} = fb.${convert}({IN});`,
319
+ })),
320
+ {
321
+ // the texts of the inputs one after the other - numbers as they are, use ROUND before
322
+ type: 'CONCAT',
323
+ category: 'convert',
324
+ inputs: [],
325
+ outputs: [{ id: 'OUT', type: 'STRING' }],
326
+ extensible: { prefix: 'IN', type: 'ANY', default: '', min: 2, max: 16 },
327
+ code: '{OUT} = fb.concat({IN*:, });',
328
+ },
329
+ // ---- control
330
+ {
331
+ // two-point switch: on above HIGH, off below LOW, as it was in between
332
+ type: 'HYST',
333
+ category: 'control',
334
+ inputs: [
335
+ { id: 'IN', type: 'REAL', default: 0 },
336
+ { id: 'HIGH', type: 'REAL', param: true, default: 1 },
337
+ { id: 'LOW', type: 'REAL', param: true, default: 0 },
338
+ ],
339
+ outputs: [{ id: 'Q', type: 'BOOL' }],
340
+ stateful: true,
341
+ code: '{I}.run({IN}, {HIGH}, {LOW}); {Q} = {I}.Q;',
342
+ },
343
+ {
344
+ // follows IN, but changes by at most UP or DOWN per second; 0 means without limit
345
+ type: 'RAMP',
346
+ category: 'control',
347
+ inputs: [
348
+ { id: 'IN', type: 'REAL', default: 0 },
349
+ { id: 'UP', type: 'REAL', param: true, default: 1 },
350
+ { id: 'DOWN', type: 'REAL', param: true, default: 1 },
351
+ ],
352
+ outputs: [{ id: 'OUT', type: 'REAL' }],
353
+ stateful: true,
354
+ timeDependent: true,
355
+ code: '{I}.run({IN}, {UP}, {DOWN}, dt, firstScan); {OUT} = {I}.OUT;',
356
+ },
357
+ {
358
+ // low pass of the first order: OUT follows IN with the time constant T
359
+ type: 'PT1',
360
+ category: 'control',
361
+ inputs: [
362
+ { id: 'IN', type: 'REAL', default: 0 },
363
+ { id: 'T', type: 'TIME', param: true, default: 10000 },
364
+ ],
365
+ outputs: [{ id: 'OUT', type: 'REAL' }],
366
+ stateful: true,
367
+ timeDependent: true,
368
+ code: '{I}.run({IN}, {T}, dt, firstScan); {OUT} = {I}.OUT;',
369
+ },
370
+ {
371
+ // PID controller: set point SP, process value PV, output Y within YMIN..YMAX
372
+ type: 'PID',
373
+ category: 'control',
374
+ inputs: [
375
+ { id: 'SP', type: 'REAL', default: 0 },
376
+ { id: 'PV', type: 'REAL', default: 0 },
377
+ { id: 'KP', type: 'REAL', param: true, default: 1 },
378
+ // reset time of the integral part, 0: none
379
+ { id: 'TN', type: 'TIME', param: true, default: 0 },
380
+ // derivative time, 0: none
381
+ { id: 'TV', type: 'TIME', param: true, default: 0 },
382
+ { id: 'YMIN', type: 'REAL', param: true, default: 0 },
383
+ { id: 'YMAX', type: 'REAL', param: true, default: 100 },
384
+ { id: 'RST', type: 'BOOL', default: false },
385
+ ],
386
+ outputs: [{ id: 'Y', type: 'REAL' }],
387
+ stateful: true,
388
+ timeDependent: true,
389
+ code: '{I}.run({SP}, {PV}, {KP}, {TN}, {TV}, {YMIN}, {YMAX}, {RST}, dt, firstScan); {Y} = {I}.Y;',
390
+ },
391
+ // ---- ioBroker
392
+ {
393
+ type: 'STATE_IN',
394
+ category: 'iobroker',
395
+ inputs: [],
396
+ outputs: [{ id: 'Q', type: { param: 'type' } }],
397
+ params: [
398
+ { id: 'oid', type: 'OID', required: true },
399
+ { id: 'type', type: 'ENUM', options: ['BOOL', 'INT', 'REAL', 'STRING'], default: 'REAL' },
400
+ ],
401
+ code: '{Q} = rt.input({$oid}, {$type});',
402
+ },
403
+ {
404
+ type: 'STATE_OUT',
405
+ category: 'iobroker',
406
+ inputs: [{ id: 'IN', type: 'ANY', default: false }],
407
+ outputs: [],
408
+ params: [
409
+ { id: 'oid', type: 'OID', required: true },
410
+ { id: 'ack', type: 'BOOL', default: false },
411
+ // at most one write per this many ms - the last value is written when it is over
412
+ { id: 'minInterval', type: 'TIME', default: 0 },
413
+ ],
414
+ code: 'rt.output({$oid}, {IN}, {$ack}, {$minInterval});',
415
+ },
416
+ {
417
+ type: 'CONST',
418
+ category: 'iobroker',
419
+ inputs: [],
420
+ outputs: [{ id: 'Q', type: { param: 'type' } }],
421
+ params: [
422
+ { id: 'type', type: 'ENUM', options: ['BOOL', 'INT', 'REAL', 'TIME', 'STRING'], default: 'REAL' },
423
+ { id: 'value', type: { param: 'type' }, default: 0 },
424
+ ],
425
+ code: '{Q} = {$value};',
426
+ },
427
+ // ---- calendar
428
+ {
429
+ // the local time, split up; WDAY: 1 Monday ... 7 Sunday
430
+ type: 'CLOCK',
431
+ category: 'calendar',
432
+ inputs: [],
433
+ outputs: [
434
+ { id: 'TOD', type: 'TIME', clock: true },
435
+ { id: 'HOUR', type: 'INT' },
436
+ { id: 'MIN', type: 'INT' },
437
+ { id: 'WDAY', type: 'INT' },
438
+ { id: 'DAY', type: 'INT' },
439
+ { id: 'MONTH', type: 'INT' },
440
+ { id: 'YEAR', type: 'INT' },
441
+ ],
442
+ stateful: true,
443
+ timeDependent: true,
444
+ code: '{I}.run(); {TOD} = {I}.TOD; {HOUR} = {I}.HOUR; {MIN} = {I}.MIN; {WDAY} = {I}.WDAY; ' +
445
+ '{DAY} = {I}.DAY; {MONTH} = {I}.MONTH; {YEAR} = {I}.YEAR;',
446
+ },
447
+ {
448
+ // true from START to END on the chosen days; a window over midnight belongs to the day it starts
449
+ type: 'TIMEWINDOW',
450
+ category: 'calendar',
451
+ inputs: [
452
+ { id: 'START', type: 'TIME', param: true, default: 8 * 3600000, clock: true },
453
+ { id: 'END', type: 'TIME', param: true, default: 22 * 3600000, clock: true },
454
+ ],
455
+ outputs: [{ id: 'Q', type: 'BOOL' }],
456
+ params: [{ id: 'days', type: 'ENUM', options: ['all', 'weekdays', 'weekend'], default: 'all' }],
457
+ timeDependent: true,
458
+ code: '{Q} = fb.timeWindow({START}, {END}, {$days});',
459
+ },
460
+ {
461
+ // a pulse of one cycle when the time of the cron pattern comes
462
+ type: 'SCHEDULE',
463
+ category: 'calendar',
464
+ inputs: [],
465
+ outputs: [{ id: 'Q', type: 'BOOL' }],
466
+ params: [{ id: 'cron', type: 'CRON', default: '0 8 * * *', required: true }],
467
+ stateful: true,
468
+ code: '{Q} = rt.cron({I}, {$cron});',
469
+ },
470
+ {
471
+ // true from one sun event to another, like from sunset to sunrise; the offsets are minutes
472
+ type: 'ASTRO',
473
+ category: 'calendar',
474
+ inputs: [],
475
+ outputs: [
476
+ { id: 'Q', type: 'BOOL' },
477
+ { id: 'START', type: 'TIME', clock: true },
478
+ { id: 'END', type: 'TIME', clock: true },
479
+ ],
480
+ params: [
481
+ { id: 'start', type: 'ENUM', options: exports.FB_ASTRO_EVENTS, default: 'sunset' },
482
+ { id: 'startOffset', type: 'INT', default: 0 },
483
+ { id: 'end', type: 'ENUM', options: exports.FB_ASTRO_EVENTS, default: 'sunrise' },
484
+ { id: 'endOffset', type: 'INT', default: 0 },
485
+ ],
486
+ timeDependent: true,
487
+ code: '{START} = rt.astro({$start}, {$startOffset}); {END} = rt.astro({$end}, {$endOffset}); ' +
488
+ '{Q} = fb.inWindow(fb.timeOfDay(), {START}, {END});',
489
+ },
490
+ // ---- messages
491
+ {
492
+ // a line in the log of ioBroker - `log()` is the one of the script sandbox
493
+ type: 'LOG',
494
+ category: 'messages',
495
+ inputs: [
496
+ { id: 'TRIG', type: 'BOOL', default: false },
497
+ { id: 'IN', type: 'ANY', default: '' },
498
+ ],
499
+ outputs: [],
500
+ params: [
501
+ { id: 'text', type: 'STRING', default: '%s' },
502
+ { id: 'level', type: 'ENUM', options: ['info', 'warn', 'error', 'debug'], default: 'info' },
503
+ { id: 'when', type: 'ENUM', options: ['edge', 'change'], default: 'edge' },
504
+ ],
505
+ stateful: true,
506
+ code: 'if ({I}.run({TRIG}, {IN}, {$text}, {$when}, dt, firstScan)) log({I}.line, {$level});',
507
+ },
508
+ {
509
+ // a message in the notifications of ioBroker, as an information or as an alert
510
+ type: 'NOTIFY',
511
+ category: 'messages',
512
+ inputs: [
513
+ { id: 'TRIG', type: 'BOOL', default: false },
514
+ { id: 'IN', type: 'ANY', default: '' },
515
+ ],
516
+ outputs: [],
517
+ params: [
518
+ { id: 'text', type: 'STRING', default: '%s' },
519
+ { id: 'category', type: 'ENUM', options: ['message', 'alert'], default: 'message' },
520
+ { id: 'when', type: 'ENUM', options: ['edge', 'change'], default: 'edge' },
521
+ ],
522
+ stateful: true,
523
+ code: 'if ({I}.run({TRIG}, {IN}, {$text}, {$when}, dt, firstScan)) rt.notify({I}, {$category});',
524
+ },
525
+ {
526
+ // a message to an adapter, like telegram.0 or pushover.0: `{ text, message, title, subject }`
527
+ type: 'SENDTO',
528
+ category: 'messages',
529
+ inputs: [
530
+ { id: 'TRIG', type: 'BOOL', default: false },
531
+ { id: 'IN', type: 'ANY', default: '' },
532
+ ],
533
+ outputs: [],
534
+ params: [
535
+ { id: 'instance', type: 'INSTANCE', required: true },
536
+ { id: 'text', type: 'STRING', default: '%s' },
537
+ { id: 'title', type: 'STRING', default: '' },
538
+ { id: 'command', type: 'STRING', default: 'send' },
539
+ { id: 'when', type: 'ENUM', options: ['edge', 'change'], default: 'edge' },
540
+ ],
541
+ stateful: true,
542
+ code: 'if ({I}.run({TRIG}, {IN}, {$text}, {$when}, dt, firstScan)) rt.send({I}, {$instance}, {$command}, {$title});',
543
+ },
544
+ // ---- expert
545
+ {
546
+ // code of the user: gets IN1..INn, dt, firstScan and state, returns OUT1 or [OUT1, OUT2, ...]
547
+ type: 'JS',
548
+ category: 'expert',
549
+ inputs: [],
550
+ outputs: [],
551
+ extensible: { prefix: 'IN', type: 'ANY', default: 0, min: 0, max: 8, count: 2 },
552
+ extensibleOutputs: { prefix: 'OUT', type: 'ANY', min: 1, max: 8 },
553
+ params: [{ id: 'code', type: 'CODE', default: 'return IN1;' }],
554
+ stateful: true,
555
+ // written by the generator itself: the code becomes a function of the script
556
+ code: '',
557
+ },
558
+ // ---- the pins of a user block, only in the diagram of a block
559
+ {
560
+ type: 'FB_IN',
561
+ category: 'interface',
562
+ inputs: [],
563
+ outputs: [{ id: 'Q', type: { param: 'type' } }],
564
+ params: [
565
+ { id: 'pin', type: 'NAME', required: true },
566
+ { id: 'type', type: 'ENUM', options: ['BOOL', 'INT', 'REAL', 'TIME', 'STRING'], default: 'BOOL' },
567
+ // what the input of an instance gets while it is not connected
568
+ { id: 'value', type: { param: 'type' }, default: false },
569
+ ],
570
+ code: '{Q} = self[{$pin}];',
571
+ },
572
+ {
573
+ type: 'FB_OUT',
574
+ category: 'interface',
575
+ inputs: [{ id: 'IN', type: { param: 'type' }, default: false }],
576
+ outputs: [],
577
+ params: [
578
+ { id: 'pin', type: 'NAME', required: true },
579
+ { id: 'type', type: 'ENUM', options: ['BOOL', 'INT', 'REAL', 'TIME', 'STRING'], default: 'BOOL' },
580
+ ],
581
+ code: 'self[{$pin}] = {IN};',
582
+ },
583
+ ];
584
+ /** The categories in the order of the palette */
585
+ exports.FB_CATEGORIES = [
586
+ 'iobroker',
587
+ 'logic',
588
+ 'memory',
589
+ 'timers',
590
+ 'counters',
591
+ 'compare',
592
+ 'arithmetic',
593
+ 'convert',
594
+ 'control',
595
+ 'calendar',
596
+ 'messages',
597
+ 'expert',
598
+ ];
599
+ const byType = new Map(exports.FB_LIBRARY.map(def => [def.type, def]));
600
+ const SIGNAL_TYPES = ['BOOL', 'INT', 'REAL', 'TIME', 'STRING'];
601
+ /** The FB_IN or FB_OUT blocks of a user block that make its pins, from top to bottom */
602
+ function getTerminals(user, type) {
603
+ return user.graph.blocks
604
+ .filter(block => block.type === type && typeof block.params?.pin === 'string' && block.params.pin)
605
+ .sort((a, b) => a.pos[1] - b.pos[1] || a.pos[0] - b.pos[0]);
606
+ }
607
+ function terminalType(block) {
608
+ const type = block.params?.type;
609
+ return SIGNAL_TYPES.includes(type) ? type : 'BOOL';
610
+ }
611
+ /** A block depends on time if one of its blocks does - also inside the user blocks it contains */
612
+ function isTimeDependent(user, userBlocks, seen) {
613
+ seen.add(user.type);
614
+ return user.graph.blocks.some(block => {
615
+ const inner = userBlocks[block.type];
616
+ if (inner) {
617
+ return !seen.has(inner.type) && isTimeDependent(inner, userBlocks, seen);
618
+ }
619
+ return !!byType.get(block.type)?.timeDependent;
620
+ });
621
+ }
622
+ /**
623
+ * A user block as a block type: its pins are its FB_IN and FB_OUT blocks. It always counts as a block
624
+ * with a state - an instance keeps its outputs from one cycle to the next, so a loop may lead through it.
625
+ */
626
+ function userBlockDef(user, userBlocks) {
627
+ return {
628
+ type: user.type,
629
+ category: 'user',
630
+ inputs: getTerminals(user, 'FB_IN').map(block => ({
631
+ id: String(block.params.pin),
632
+ type: terminalType(block),
633
+ default: block.params?.value,
634
+ })),
635
+ outputs: getTerminals(user, 'FB_OUT').map(block => ({
636
+ id: String(block.params.pin),
637
+ type: terminalType(block),
638
+ })),
639
+ stateful: true,
640
+ timeDependent: isTimeDependent(user, userBlocks, new Set()),
641
+ code: '',
642
+ user,
643
+ };
644
+ }
645
+ /**
646
+ * The type of a block: one of the library, or a user block of `userBlocks` - the copies a diagram
647
+ * carries of the blocks it uses.
648
+ */
649
+ function getBlockDef(type, userBlocks) {
650
+ const def = byType.get(type);
651
+ if (def) {
652
+ return def;
653
+ }
654
+ const user = userBlocks?.[type];
655
+ return user ? userBlockDef(user, userBlocks) : undefined;
656
+ }
657
+ //# sourceMappingURL=library.js.map