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.
- package/README.md +6 -14
- package/admin/assets/AiChatPanel-CpY4Bun-.js +27 -0
- package/admin/assets/{AiChatService-BOL3J2Jd.js → AiChatService-QKcpW4jQ.js} +1 -1
- package/admin/assets/AiDiffView-DscPfZ38.js +1 -0
- package/admin/assets/{AiInlineProvider-BIlcrTkS.js → AiInlineProvider-DTSPKoXG.js} +1 -1
- package/admin/assets/BlocklyEditor-BZyoN1JE.js +301 -0
- package/admin/assets/Compile-B0uHjrBE.css +1 -0
- package/admin/assets/Compile-Oss28m_f.js +165 -0
- package/admin/assets/{Debugger-DwHHsh9O.js → Debugger-teJTIU-2.js} +4 -4
- package/admin/assets/{Documentation-Bc0RmoEF.js → Documentation-uz4Ut9pT.js} +4 -4
- package/admin/assets/ExpandMore-V5Ix1QB1.js +1 -0
- package/admin/assets/FbEditor-B8S-mCvc.css +1 -0
- package/admin/assets/FbEditor-aOZ-RpPV.js +15 -0
- package/admin/assets/Import-BIC5Ee9z.js +1 -0
- package/admin/assets/NotificationsActive-BdzH44gp.js +1 -0
- package/admin/assets/RulesEditor-CcDVthPa.js +1 -0
- package/admin/assets/{ScriptEditor-CEHpEFp7.js → ScriptEditor-CviB6Hif.js} +2 -2
- package/admin/assets/ScriptEditorVanillaMonaco-ByuXwybM.js +3 -0
- package/admin/assets/Send-Mdo32jMb.js +1 -0
- 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
- 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
- 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
- package/admin/assets/aiPromptBuilder-yTB6N2VT.js +1 -0
- package/admin/assets/blocklyTheme-CGhU3cEO.js +1 -0
- package/admin/assets/blocks_action-BQ4O7NRE.js +1 -0
- package/admin/assets/{blocks_convert-BP2RjhQH.js → blocks_convert-0VBjfhqQ.js} +1 -1
- package/admin/assets/blocks_logic-DAo99xDr.js +1 -0
- package/admin/assets/blocks_number-C--e19NU.js +1 -0
- package/admin/assets/blocks_object-D0TPhdzg.js +1 -0
- package/admin/assets/blocks_procedures-DgTxgXdB.js +3 -0
- package/admin/assets/{blocks_sendto-qIKzOAcV.js → blocks_sendto-CRIrtOUc.js} +1 -1
- package/admin/assets/blocks_switch-b_GYfF0n.js +2 -0
- package/admin/assets/blocks_system-BdkUdSsc.js +1 -0
- package/admin/assets/blocks_text-DSFhEVOf.js +1 -0
- package/admin/assets/blocks_time-CqALAiJp.js +1 -0
- package/admin/assets/blocks_timeout-yrOD2pZp.js +1 -0
- package/admin/assets/{blocks_trigger-CnmXLCUE.js → blocks_trigger-DeAYXpSS.js} +1 -1
- package/admin/assets/{cronHoverProvider-CcIFAhVy.js → cronHoverProvider-DoO2_tpG.js} +1 -1
- package/admin/assets/{field_cron-Ba46q8Qc.js → field_cron-D3Ts_s9M.js} +1 -1
- package/admin/assets/{field_oid-lWCjOzuq.js → field_oid-BRNXredg.js} +1 -1
- package/admin/assets/{field_script-BCWZHhnW.js → field_script-3X6ousg7.js} +1 -1
- package/admin/assets/helpers-BTGaTdnT.js +1 -0
- package/admin/assets/{hostInit-CVybS7BB.js → hostInit-2h2Cbsaw.js} +1 -1
- package/admin/assets/index-BHhhebRG.css +1 -0
- package/admin/assets/index-CbQlIKB_.js +156 -0
- package/admin/assets/{inlineChatWidget-N8xIkvxX.js → inlineChatWidget-BwQVCPkx.js} +2 -2
- package/admin/assets/{inlineDiffController-BuqYsKKq.js → inlineDiffController-BsDDsDHn.js} +2 -2
- package/admin/assets/loadBlocks-RpqM7PwO.js +117 -0
- package/admin/assets/loadMonaco-BVOEahNw.js +1 -0
- package/admin/assets/{mf-entry-bootstrap-0-a5a39621.js → mf-entry-bootstrap-0-0deef484.js} +3 -3
- package/admin/assets/{pendingShares-DOAkyFMS.js → pendingShares-BaAadIDv.js} +1 -1
- package/admin/assets/reactour.esm-DX9ZgYlx.js +137 -0
- package/admin/assets/{stateHoverProvider-BYAbe1Ay.js → stateHoverProvider-BEadnSXp.js} +1 -1
- package/admin/assets/tileFbd-CWAy7R7m.svg +85 -0
- package/admin/mf-manifest.json +1 -1
- package/admin/mf-stats.json +1 -1
- package/admin/remoteEntry.js +2 -2
- package/admin/tab.html +3 -7
- package/build/lib/fb/analyze.js +288 -0
- package/build/lib/fb/analyze.js.map +1 -0
- package/build/lib/fb/blocks.js +605 -0
- package/build/lib/fb/blocks.js.map +1 -0
- package/build/lib/fb/generate.js +326 -0
- package/build/lib/fb/generate.js.map +1 -0
- package/build/lib/fb/graph.js +240 -0
- package/build/lib/fb/graph.js.map +1 -0
- package/build/lib/fb/index.js +57 -0
- package/build/lib/fb/index.js.map +1 -0
- package/build/lib/fb/js.js +33 -0
- package/build/lib/fb/js.js.map +1 -0
- package/build/lib/fb/layout.js +205 -0
- package/build/lib/fb/layout.js.map +1 -0
- package/build/lib/fb/library.js +657 -0
- package/build/lib/fb/library.js.map +1 -0
- package/build/lib/fb/runtime.js +793 -0
- package/build/lib/fb/runtime.js.map +1 -0
- package/build/lib/fb/time.js +76 -0
- package/build/lib/fb/time.js.map +1 -0
- package/build/lib/fb/types.js +19 -0
- package/build/lib/fb/types.js.map +1 -0
- package/build/lib/fb/user.js +78 -0
- package/build/lib/fb/user.js.map +1 -0
- package/build/lib/javascript.d.ts +1 -1
- package/build/lib/mirror.js +4 -0
- package/build/lib/mirror.js.map +1 -1
- package/build/lib/sandbox.js +44 -0
- package/build/lib/sandbox.js.map +1 -1
- package/build/main.js +66 -1
- package/build/main.js.map +1 -1
- package/build/types.d.ts +9 -1
- package/docs/de/fbd.md +274 -0
- package/docs/en/fbd.md +260 -0
- package/io-package.json +39 -15
- package/package.json +1 -1
- package/admin/assets/AiChatPanel-oBeXbUFv.js +0 -27
- package/admin/assets/AiDiffView-C-KKjnJD.js +0 -1
- package/admin/assets/Error-DZ4vCykD.js +0 -1
- package/admin/assets/Import-Cu02ceLW.js +0 -1
- package/admin/assets/RulesEditor-QCbi1lV_.js +0 -1
- package/admin/assets/ScriptEditorVanillaMonaco-ChQmnk0p.js +0 -3
- package/admin/assets/aiPromptBuilder-DKler0UK.js +0 -1
- package/admin/assets/blocks_action-DywZVfRY.js +0 -1
- package/admin/assets/blocks_logic-CdTl5YZw.js +0 -1
- package/admin/assets/blocks_number-DXFd9Rva.js +0 -1
- package/admin/assets/blocks_object-by1uBDHi.js +0 -1
- package/admin/assets/blocks_procedures-BcJ7N70D.js +0 -3
- package/admin/assets/blocks_switch-dLF6hSJl.js +0 -2
- package/admin/assets/blocks_system-DmX-SBy8.js +0 -1
- package/admin/assets/blocks_text-BI4zNU3o.js +0 -1
- package/admin/assets/blocks_time-BgYA4Y_4.js +0 -1
- package/admin/assets/blocks_timeout-DUzgMyAu.js +0 -1
- package/admin/assets/helpers-CnEjYAup.js +0 -1
- package/admin/assets/index-B3s0zmWC.js +0 -871
- 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
|