iobroker.javascript 7.10.2 → 7.11.1
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 +15 -10
- package/admin/asset-manifest.json +5 -5
- package/admin/google-blockly/own/blocks_action.js +305 -22
- package/admin/google-blockly/own/blocks_object.js +3 -3
- package/admin/google-blockly/own/blocks_system.js +10 -13
- package/admin/google-blockly/own/blocks_trigger.js +74 -6
- package/admin/google-blockly/own/blocks_words.js +50 -16
- package/admin/google-blockly/own/field_oid.js +7 -1
- package/admin/static/js/184.985be7e8.chunk.js +2 -0
- package/admin/static/js/184.985be7e8.chunk.js.map +1 -0
- package/admin/static/js/{main.4caef13e.js → main.f0e610b0.js} +2 -2
- package/admin/static/js/{main.4caef13e.js.map → main.f0e610b0.js.map} +1 -1
- package/admin/tab.html +1 -1
- package/docs/en/javascript.md +16 -0
- package/io-package.json +27 -27
- package/lib/javascript.d.ts +6 -3
- package/lib/protectFs.js +10 -8
- package/lib/sandbox.js +70 -133
- package/lib/tools.js +48 -3
- package/main.js +4 -2
- package/package.json +2 -2
- package/admin/static/js/184.23703866.chunk.js +0 -2
- package/admin/static/js/184.23703866.chunk.js.map +0 -1
package/README.md
CHANGED
|
@@ -42,6 +42,21 @@ Since v5.5.0 of the JavaScript adapter the following locations (relative to the
|
|
|
42
42
|
<!--
|
|
43
43
|
### **WORK IN PROGRESS**
|
|
44
44
|
-->
|
|
45
|
+
### 7.11.1 (2024-03-28)
|
|
46
|
+
|
|
47
|
+
* (klein0r) Added exec result blockly block
|
|
48
|
+
* (klein0r) Protect iobroker-data/files to avoid direct writes with node:fs
|
|
49
|
+
* (klein0r) Escape single quotes in blockly obj attributes
|
|
50
|
+
|
|
51
|
+
### 7.11.0 (2024-03-26)
|
|
52
|
+
|
|
53
|
+
* (klein0r) Added blockly block for read and write file
|
|
54
|
+
* (klein0r) Allow to select other object types than state in some blocks
|
|
55
|
+
* (klein0r) Improved translations
|
|
56
|
+
* (klein0r) Removed 'type' from dropdown (is always 'state')
|
|
57
|
+
* (klein0r) Use highlight in search (instead of select)
|
|
58
|
+
* (klein0r) Added option for httpGet to receive arraybuffer (download files)
|
|
59
|
+
|
|
45
60
|
### 7.10.2 (2024-03-25)
|
|
46
61
|
|
|
47
62
|
* (klein0r) Fixed httpGet/httpPost issue when using without options
|
|
@@ -58,16 +73,6 @@ Since v5.5.0 of the JavaScript adapter the following locations (relative to the
|
|
|
58
73
|
* (klein0r) Copy date object in getAstroDate
|
|
59
74
|
* (klein0r) Added object id as tooltip
|
|
60
75
|
|
|
61
|
-
### 7.9.4 (2024-03-20)
|
|
62
|
-
|
|
63
|
-
* (klein0r) Fixed urlencoding for basic auth in url (user:pass)
|
|
64
|
-
* (klein0r) Added warning icon if trigger is positioned inside of another trigger or loop
|
|
65
|
-
|
|
66
|
-
### 7.9.3 (2024-03-19)
|
|
67
|
-
|
|
68
|
-
* (klein0r) Added timeout option for http blocks
|
|
69
|
-
* (klein0r) Added option for basic auth in url (user:pass)
|
|
70
|
-
|
|
71
76
|
## License
|
|
72
77
|
The MIT License (MIT)
|
|
73
78
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"files": {
|
|
3
|
-
"main.js": "/static/js/main.
|
|
3
|
+
"main.js": "/static/js/main.f0e610b0.js",
|
|
4
4
|
"static/css/184.7463f8b6.chunk.css": "/static/css/184.7463f8b6.chunk.css",
|
|
5
|
-
"static/js/184.
|
|
5
|
+
"static/js/184.985be7e8.chunk.js": "/static/js/184.985be7e8.chunk.js",
|
|
6
6
|
"static/js/966.088c1225.chunk.js": "/static/js/966.088c1225.chunk.js",
|
|
7
7
|
"static/js/30.8bf17a3b.chunk.js": "/static/js/30.8bf17a3b.chunk.js",
|
|
8
8
|
"static/js/704.4ede9892.chunk.js": "/static/js/704.4ede9892.chunk.js",
|
|
@@ -160,9 +160,9 @@
|
|
|
160
160
|
"static/media/Garage Doors.svg": "/static/media/Garage Doors.0c2a1cfca7ad1ea59625.svg",
|
|
161
161
|
"static/media/Outdoor Blinds.svg": "/static/media/Outdoor Blinds.37b85a9c060a4af48da9.svg",
|
|
162
162
|
"static/media/Upstairs.svg": "/static/media/Upstairs.441813e54e0daca0882d.svg",
|
|
163
|
-
"main.
|
|
163
|
+
"main.f0e610b0.js.map": "/static/js/main.f0e610b0.js.map",
|
|
164
164
|
"184.7463f8b6.chunk.css.map": "/static/css/184.7463f8b6.chunk.css.map",
|
|
165
|
-
"184.
|
|
165
|
+
"184.985be7e8.chunk.js.map": "/static/js/184.985be7e8.chunk.js.map",
|
|
166
166
|
"966.088c1225.chunk.js.map": "/static/js/966.088c1225.chunk.js.map",
|
|
167
167
|
"30.8bf17a3b.chunk.js.map": "/static/js/30.8bf17a3b.chunk.js.map",
|
|
168
168
|
"704.4ede9892.chunk.js.map": "/static/js/704.4ede9892.chunk.js.map",
|
|
@@ -195,6 +195,6 @@
|
|
|
195
195
|
"77.f4bb7c45.chunk.js.map": "/static/js/77.f4bb7c45.chunk.js.map"
|
|
196
196
|
},
|
|
197
197
|
"entrypoints": [
|
|
198
|
-
"static/js/main.
|
|
198
|
+
"static/js/main.f0e610b0.js"
|
|
199
199
|
]
|
|
200
200
|
}
|
|
@@ -20,7 +20,7 @@ Blockly.Action.blocks['exec'] =
|
|
|
20
20
|
'<block type="exec">'
|
|
21
21
|
+ ' <value name="COMMAND">'
|
|
22
22
|
+ ' <shadow type="text">'
|
|
23
|
-
+ ' <field name="TEXT">
|
|
23
|
+
+ ' <field name="TEXT">pwd</field>'
|
|
24
24
|
+ ' </shadow>'
|
|
25
25
|
+ ' </value>'
|
|
26
26
|
+ ' <value name="LOG">'
|
|
@@ -33,7 +33,7 @@ Blockly.Action.blocks['exec'] =
|
|
|
33
33
|
Blockly.Blocks['exec'] = {
|
|
34
34
|
init: function() {
|
|
35
35
|
this.appendDummyInput('TEXT')
|
|
36
|
-
.appendField(Blockly.Translate('exec'));
|
|
36
|
+
.appendField('» ' + Blockly.Translate('exec'));
|
|
37
37
|
|
|
38
38
|
this.appendValueInput('COMMAND')
|
|
39
39
|
.appendField(Blockly.Translate('exec_command'));
|
|
@@ -96,7 +96,7 @@ Blockly.JavaScript['exec'] = function(block) {
|
|
|
96
96
|
|
|
97
97
|
let logText;
|
|
98
98
|
if (logLevel) {
|
|
99
|
-
logText =
|
|
99
|
+
logText = `console.${logLevel}('exec: ' + ${value_command});\n`;
|
|
100
100
|
} else {
|
|
101
101
|
logText = '';
|
|
102
102
|
}
|
|
@@ -104,18 +104,83 @@ Blockly.JavaScript['exec'] = function(block) {
|
|
|
104
104
|
if (withStatement === 'TRUE' || withStatement === 'true' || withStatement === true) {
|
|
105
105
|
const statement = Blockly.JavaScript.statementToCode(block, 'STATEMENT');
|
|
106
106
|
if (statement) {
|
|
107
|
-
return
|
|
108
|
-
|
|
107
|
+
return `exec(${value_command}, async (error, result, stderr) => {\n` +
|
|
108
|
+
statement +
|
|
109
|
+
`});\n${logText}`;
|
|
109
110
|
} else {
|
|
110
|
-
return
|
|
111
|
-
logText;
|
|
111
|
+
return `exec(${value_command});\n${logText}`;
|
|
112
112
|
}
|
|
113
113
|
} else {
|
|
114
|
-
return
|
|
115
|
-
logText;
|
|
114
|
+
return `exec(${value_command});\n${logText}`;
|
|
116
115
|
}
|
|
117
116
|
};
|
|
118
117
|
|
|
118
|
+
// --- exec_result -----------------------------------------------------------
|
|
119
|
+
Blockly.Action.blocks['exec_result'] =
|
|
120
|
+
'<block type="exec_result">'
|
|
121
|
+
+ ' <value name="ATTR">'
|
|
122
|
+
+ ' </value>'
|
|
123
|
+
+ '</block>';
|
|
124
|
+
|
|
125
|
+
Blockly.Blocks['exec_result'] = {
|
|
126
|
+
/**
|
|
127
|
+
* Block for conditionally returning a value from a procedure.
|
|
128
|
+
* @this Blockly.Block
|
|
129
|
+
*/
|
|
130
|
+
init: function() {
|
|
131
|
+
this.appendDummyInput()
|
|
132
|
+
.appendField('»');
|
|
133
|
+
|
|
134
|
+
this.appendDummyInput('ATTR')
|
|
135
|
+
.appendField(new Blockly.FieldDropdown([
|
|
136
|
+
[Blockly.Translate('exec_result_result'), 'result'],
|
|
137
|
+
[Blockly.Translate('exec_result_stderr'), 'stderr'],
|
|
138
|
+
[Blockly.Translate('exec_result_error'), 'error'],
|
|
139
|
+
]), 'ATTR');
|
|
140
|
+
|
|
141
|
+
this.setInputsInline(true);
|
|
142
|
+
this.setOutput(true);
|
|
143
|
+
this.setColour(Blockly.Action.HUE);
|
|
144
|
+
this.setTooltip(Blockly.Translate('exec_result_tooltip'));
|
|
145
|
+
//this.setHelpUrl(getHelp('exec'));
|
|
146
|
+
},
|
|
147
|
+
/**
|
|
148
|
+
* Called whenever anything on the workspace changes.
|
|
149
|
+
* Add warning if this flow block is not nested inside a loop.
|
|
150
|
+
* @param {!Blockly.Events.Abstract} e Change event.
|
|
151
|
+
* @this Blockly.Block
|
|
152
|
+
*/
|
|
153
|
+
onchange: function(e) {
|
|
154
|
+
let legal = false;
|
|
155
|
+
// Is the block nested in an exec?
|
|
156
|
+
let block = this;
|
|
157
|
+
do {
|
|
158
|
+
if (this.FUNCTION_TYPES.includes(block.type)) {
|
|
159
|
+
legal = true;
|
|
160
|
+
break;
|
|
161
|
+
}
|
|
162
|
+
block = block.getSurroundParent();
|
|
163
|
+
} while (block);
|
|
164
|
+
|
|
165
|
+
if (legal) {
|
|
166
|
+
this.setWarningText(null, this.id);
|
|
167
|
+
} else {
|
|
168
|
+
this.setWarningText(Blockly.Translate('exec_result_warning'), this.id);
|
|
169
|
+
}
|
|
170
|
+
},
|
|
171
|
+
/**
|
|
172
|
+
* List of block types that are functions and thus do not need warnings.
|
|
173
|
+
* To add a new function type add this to your code:
|
|
174
|
+
* Blockly.Blocks['procedures_ifreturn'].FUNCTION_TYPES.push('custom_func');
|
|
175
|
+
*/
|
|
176
|
+
FUNCTION_TYPES: ['exec'],
|
|
177
|
+
};
|
|
178
|
+
Blockly.JavaScript['exec_result'] = function(block) {
|
|
179
|
+
const attr = block.getFieldValue('ATTR');
|
|
180
|
+
|
|
181
|
+
return [attr, Blockly.JavaScript.ORDER_ATOMIC];
|
|
182
|
+
};
|
|
183
|
+
|
|
119
184
|
// --- action http_get --------------------------------------------------
|
|
120
185
|
Blockly.Action.blocks['http_get'] =
|
|
121
186
|
'<block type="http_get">'
|
|
@@ -128,6 +193,8 @@ Blockly.Action.blocks['http_get'] =
|
|
|
128
193
|
+ ' </value>'
|
|
129
194
|
+ ' <value name="UNIT">'
|
|
130
195
|
+ ' </value>'
|
|
196
|
+
+ ' <value name="TYPE">'
|
|
197
|
+
+ ' </value>'
|
|
131
198
|
+ ' <value name="STATEMENT">'
|
|
132
199
|
+ ' </value>'
|
|
133
200
|
+ '</block>';
|
|
@@ -135,16 +202,23 @@ Blockly.Action.blocks['http_get'] =
|
|
|
135
202
|
Blockly.Blocks['http_get'] = {
|
|
136
203
|
init: function() {
|
|
137
204
|
this.appendValueInput('URL')
|
|
138
|
-
.appendField(Blockly.Translate('http_get'));
|
|
205
|
+
.appendField('🌐 ' + Blockly.Translate('http_get'));
|
|
139
206
|
|
|
140
207
|
this.appendDummyInput()
|
|
141
|
-
.appendField(Blockly.Translate('
|
|
208
|
+
.appendField(Blockly.Translate('http_timeout'))
|
|
142
209
|
.appendField(new Blockly.FieldTextInput(2000), 'TIMEOUT')
|
|
143
210
|
.appendField(new Blockly.FieldDropdown([
|
|
144
|
-
[Blockly.Translate('
|
|
145
|
-
[Blockly.Translate('
|
|
211
|
+
[Blockly.Translate('http_timeout_ms'), 'ms'],
|
|
212
|
+
[Blockly.Translate('http_timeout_sec'), 'sec']
|
|
146
213
|
]), 'UNIT');
|
|
147
214
|
|
|
215
|
+
this.appendDummyInput('TYPE')
|
|
216
|
+
.appendField(Blockly.Translate('http_type'))
|
|
217
|
+
.appendField(new Blockly.FieldDropdown([
|
|
218
|
+
[Blockly.Translate('http_type_text'), 'text'],
|
|
219
|
+
[Blockly.Translate('http_type_arraybuffer'), 'arraybuffer'],
|
|
220
|
+
]), 'TYPE');
|
|
221
|
+
|
|
148
222
|
this.appendStatementInput('STATEMENT')
|
|
149
223
|
.setCheck(null);
|
|
150
224
|
|
|
@@ -170,7 +244,12 @@ Blockly.JavaScript['http_get'] = function(block) {
|
|
|
170
244
|
timeout *= 1000;
|
|
171
245
|
}
|
|
172
246
|
|
|
173
|
-
|
|
247
|
+
let responseType = block.getFieldValue('TYPE');
|
|
248
|
+
if (!responseType) {
|
|
249
|
+
responseType = 'text';
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
return `httpGet(${URL}, { timeout: ${timeout}, responseType: '${responseType}' }, async (err, response) => {\n` +
|
|
174
253
|
Blockly.JavaScript.prefixLines(`if (err) {`, Blockly.JavaScript.INDENT) + '\n' +
|
|
175
254
|
Blockly.JavaScript.prefixLines(`console.error(err);`, Blockly.JavaScript.INDENT + Blockly.JavaScript.INDENT) + '\n' +
|
|
176
255
|
Blockly.JavaScript.prefixLines(`}`, Blockly.JavaScript.INDENT) + '\n' +
|
|
@@ -190,6 +269,8 @@ Blockly.Action.blocks['http_post'] =
|
|
|
190
269
|
+ ' </value>'
|
|
191
270
|
+ ' <value name="UNIT">'
|
|
192
271
|
+ ' </value>'
|
|
272
|
+
+ ' <value name="TYPE">'
|
|
273
|
+
+ ' </value>'
|
|
193
274
|
+ ' <value name="DATA">'
|
|
194
275
|
+ ' <shadow type="object_new">'
|
|
195
276
|
+ ' </shadow>'
|
|
@@ -201,16 +282,23 @@ Blockly.Action.blocks['http_post'] =
|
|
|
201
282
|
Blockly.Blocks['http_post'] = {
|
|
202
283
|
init: function() {
|
|
203
284
|
this.appendValueInput('URL')
|
|
204
|
-
.appendField(Blockly.Translate('http_post'));
|
|
285
|
+
.appendField('🌐 ' + Blockly.Translate('http_post'));
|
|
205
286
|
|
|
206
287
|
this.appendDummyInput()
|
|
207
|
-
.appendField(Blockly.Translate('
|
|
288
|
+
.appendField(Blockly.Translate('http_timeout'))
|
|
208
289
|
.appendField(new Blockly.FieldTextInput(2000), 'TIMEOUT')
|
|
209
290
|
.appendField(new Blockly.FieldDropdown([
|
|
210
|
-
[Blockly.Translate('
|
|
211
|
-
[Blockly.Translate('
|
|
291
|
+
[Blockly.Translate('http_timeout_ms'), 'ms'],
|
|
292
|
+
[Blockly.Translate('http_timeout_sec'), 'sec']
|
|
212
293
|
]), 'UNIT');
|
|
213
294
|
|
|
295
|
+
this.appendDummyInput('TYPE')
|
|
296
|
+
.appendField(Blockly.Translate('http_type'))
|
|
297
|
+
.appendField(new Blockly.FieldDropdown([
|
|
298
|
+
[Blockly.Translate('http_type_text'), 'text'],
|
|
299
|
+
[Blockly.Translate('http_type_arraybuffer'), 'arraybuffer'],
|
|
300
|
+
]), 'TYPE');
|
|
301
|
+
|
|
214
302
|
this.appendValueInput('DATA')
|
|
215
303
|
.appendField(Blockly.Translate('http_post_data'));
|
|
216
304
|
|
|
@@ -240,11 +328,16 @@ Blockly.JavaScript['http_post'] = function(block) {
|
|
|
240
328
|
timeout *= 1000;
|
|
241
329
|
}
|
|
242
330
|
|
|
331
|
+
let responseType = block.getFieldValue('TYPE');
|
|
332
|
+
if (!responseType) {
|
|
333
|
+
responseType = 'text';
|
|
334
|
+
}
|
|
335
|
+
|
|
243
336
|
if (!data) {
|
|
244
337
|
data = 'null';
|
|
245
338
|
}
|
|
246
339
|
|
|
247
|
-
return `httpPost(${URL}, ${data}, { timeout: ${timeout} }, async (err, response) => {\n` +
|
|
340
|
+
return `httpPost(${URL}, ${data}, { timeout: ${timeout}, responseType: '${responseType}' }, async (err, response) => {\n` +
|
|
248
341
|
Blockly.JavaScript.prefixLines(`if (err) {`, Blockly.JavaScript.INDENT) + '\n' +
|
|
249
342
|
Blockly.JavaScript.prefixLines(`console.error(err);`, Blockly.JavaScript.INDENT + Blockly.JavaScript.INDENT) + '\n' +
|
|
250
343
|
Blockly.JavaScript.prefixLines(`}`, Blockly.JavaScript.INDENT) + '\n' +
|
|
@@ -252,7 +345,7 @@ Blockly.JavaScript['http_post'] = function(block) {
|
|
|
252
345
|
'});\n';
|
|
253
346
|
};
|
|
254
347
|
|
|
255
|
-
// ---
|
|
348
|
+
// --- http_response -----------------------------------------------------------
|
|
256
349
|
Blockly.Action.blocks['http_response'] =
|
|
257
350
|
'<block type="http_response">'
|
|
258
351
|
+ ' <value name="ATTR">'
|
|
@@ -276,7 +369,7 @@ Blockly.Blocks['http_response'] = {
|
|
|
276
369
|
|
|
277
370
|
this.setInputsInline(true);
|
|
278
371
|
this.setOutput(true);
|
|
279
|
-
this.setColour(Blockly.
|
|
372
|
+
this.setColour(Blockly.Action.HUE);
|
|
280
373
|
this.setTooltip(Blockly.Translate('http_response_tooltip'));
|
|
281
374
|
//this.setHelpUrl(getHelp('http_response'));
|
|
282
375
|
},
|
|
@@ -317,6 +410,196 @@ Blockly.JavaScript['http_response'] = function(block) {
|
|
|
317
410
|
return [attr, Blockly.JavaScript.ORDER_ATOMIC];
|
|
318
411
|
};
|
|
319
412
|
|
|
413
|
+
// --- action file_write --------------------------------------------------
|
|
414
|
+
Blockly.Action.blocks['file_write'] =
|
|
415
|
+
'<block type="file_write">'
|
|
416
|
+
+ ' <value name="OID">'
|
|
417
|
+
+ ' <shadow type="field_oid_meta">'
|
|
418
|
+
+ ' <field name="oid">0_userdata.0</field>'
|
|
419
|
+
+ ' </shadow>'
|
|
420
|
+
+ ' </value>'
|
|
421
|
+
+ ' <value name="FILE">'
|
|
422
|
+
+ ' <shadow type="text">'
|
|
423
|
+
+ ' <field name="TEXT">demo.json</field>'
|
|
424
|
+
+ ' </shadow>'
|
|
425
|
+
+ ' </value>'
|
|
426
|
+
+ ' <value name="DATA">'
|
|
427
|
+
+ ' </value>'
|
|
428
|
+
+ '</block>';
|
|
429
|
+
|
|
430
|
+
Blockly.Blocks['file_write'] = {
|
|
431
|
+
init: function() {
|
|
432
|
+
this.appendValueInput('OID')
|
|
433
|
+
.appendField('📁 ' + Blockly.Translate('file_write'));
|
|
434
|
+
|
|
435
|
+
this.appendValueInput('FILE')
|
|
436
|
+
.appendField(Blockly.Translate('file_write_filename'))
|
|
437
|
+
.setCheck(null);
|
|
438
|
+
|
|
439
|
+
this.appendValueInput('DATA')
|
|
440
|
+
.appendField(Blockly.Translate('file_write_data'));
|
|
441
|
+
|
|
442
|
+
this.setInputsInline(false);
|
|
443
|
+
this.setPreviousStatement(true, null);
|
|
444
|
+
this.setNextStatement(true, null);
|
|
445
|
+
|
|
446
|
+
this.setColour(Blockly.Action.HUE);
|
|
447
|
+
this.setTooltip(Blockly.Translate('file_write_tooltip'));
|
|
448
|
+
this.setHelpUrl(getHelp('file_write_help'));
|
|
449
|
+
}
|
|
450
|
+
};
|
|
451
|
+
|
|
452
|
+
Blockly.JavaScript['file_write'] = function(block) {
|
|
453
|
+
const value_objectid = Blockly.JavaScript.valueToCode(block, 'OID', Blockly.JavaScript.ORDER_ATOMIC);
|
|
454
|
+
const file = Blockly.JavaScript.valueToCode(block, 'FILE', Blockly.JavaScript.ORDER_ATOMIC);
|
|
455
|
+
const data = Blockly.JavaScript.valueToCode(block, 'DATA', Blockly.JavaScript.ORDER_ATOMIC);
|
|
456
|
+
|
|
457
|
+
let objectName = '';
|
|
458
|
+
try {
|
|
459
|
+
const objId = eval(value_objectid); // Code to string
|
|
460
|
+
objectName = main.objects[objId] && main.objects[objId].common && main.objects[objId].common.name ? main.objects[objId].common.name : '';
|
|
461
|
+
if (typeof objectName === 'object') {
|
|
462
|
+
objectName = objectName[systemLang] || objectName.en;
|
|
463
|
+
}
|
|
464
|
+
} catch (error) {
|
|
465
|
+
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
return `writeFile(${value_objectid}${objectName ? ` /* ${objectName} */` : ''}, String(${file}), ${data ? data : 'null'}, (err) => {\n` +
|
|
469
|
+
Blockly.JavaScript.prefixLines(`if (err) {`, Blockly.JavaScript.INDENT) + '\n' +
|
|
470
|
+
Blockly.JavaScript.prefixLines(`console.error(err);`, Blockly.JavaScript.INDENT + Blockly.JavaScript.INDENT) + '\n' +
|
|
471
|
+
Blockly.JavaScript.prefixLines(`}`, Blockly.JavaScript.INDENT) + '\n' +
|
|
472
|
+
'});\n';
|
|
473
|
+
};
|
|
474
|
+
|
|
475
|
+
// --- action file_read --------------------------------------------------
|
|
476
|
+
Blockly.Action.blocks['file_read'] =
|
|
477
|
+
'<block type="file_read">'
|
|
478
|
+
+ ' <value name="OID">'
|
|
479
|
+
+ ' <shadow type="field_oid_meta">'
|
|
480
|
+
+ ' <field name="oid">0_userdata.0</field>'
|
|
481
|
+
+ ' </shadow>'
|
|
482
|
+
+ ' </value>'
|
|
483
|
+
+ ' <value name="FILE">'
|
|
484
|
+
+ ' <shadow type="text">'
|
|
485
|
+
+ ' <field name="TEXT">demo.json</field>'
|
|
486
|
+
+ ' </shadow>'
|
|
487
|
+
+ ' </value>'
|
|
488
|
+
+ ' <value name="STATEMENT">'
|
|
489
|
+
+ ' </value>'
|
|
490
|
+
+ '</block>';
|
|
491
|
+
|
|
492
|
+
Blockly.Blocks['file_read'] = {
|
|
493
|
+
init: function() {
|
|
494
|
+
this.appendValueInput('OID')
|
|
495
|
+
.appendField('📁 ' + Blockly.Translate('file_read'));
|
|
496
|
+
|
|
497
|
+
this.appendValueInput('FILE')
|
|
498
|
+
.appendField(Blockly.Translate('file_read_filename'))
|
|
499
|
+
.setCheck(null);
|
|
500
|
+
|
|
501
|
+
this.appendStatementInput('STATEMENT')
|
|
502
|
+
.setCheck(null);
|
|
503
|
+
|
|
504
|
+
this.setInputsInline(false);
|
|
505
|
+
this.setPreviousStatement(true, null);
|
|
506
|
+
this.setNextStatement(true, null);
|
|
507
|
+
|
|
508
|
+
this.setColour(Blockly.Action.HUE);
|
|
509
|
+
this.setTooltip(Blockly.Translate('file_read_tooltip'));
|
|
510
|
+
this.setHelpUrl(getHelp('file_read_help'));
|
|
511
|
+
}
|
|
512
|
+
};
|
|
513
|
+
|
|
514
|
+
Blockly.JavaScript['file_read'] = function(block) {
|
|
515
|
+
const value_objectid = Blockly.JavaScript.valueToCode(block, 'OID', Blockly.JavaScript.ORDER_ATOMIC);
|
|
516
|
+
const file = Blockly.JavaScript.valueToCode(block, 'FILE', Blockly.JavaScript.ORDER_ATOMIC);
|
|
517
|
+
const statement = Blockly.JavaScript.statementToCode(block, 'STATEMENT');
|
|
518
|
+
|
|
519
|
+
let objectName = '';
|
|
520
|
+
try {
|
|
521
|
+
const objId = eval(value_objectid); // Code to string
|
|
522
|
+
objectName = main.objects[objId] && main.objects[objId].common && main.objects[objId].common.name ? main.objects[objId].common.name : '';
|
|
523
|
+
if (typeof objectName === 'object') {
|
|
524
|
+
objectName = objectName[systemLang] || objectName.en;
|
|
525
|
+
}
|
|
526
|
+
} catch (error) {
|
|
527
|
+
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
return `readFile(${value_objectid}${objectName ? ` /* ${objectName} */` : ''}, String(${file}), (err, data, mimeType) => {\n` +
|
|
531
|
+
Blockly.JavaScript.prefixLines(`if (err) {`, Blockly.JavaScript.INDENT) + '\n' +
|
|
532
|
+
Blockly.JavaScript.prefixLines(`console.error(err);`, Blockly.JavaScript.INDENT + Blockly.JavaScript.INDENT) + '\n' +
|
|
533
|
+
Blockly.JavaScript.prefixLines(`}`, Blockly.JavaScript.INDENT) + '\n' +
|
|
534
|
+
statement +
|
|
535
|
+
'});\n';
|
|
536
|
+
};
|
|
537
|
+
|
|
538
|
+
// --- file_data -----------------------------------------------------------
|
|
539
|
+
Blockly.Action.blocks['file_data'] =
|
|
540
|
+
'<block type="file_data">'
|
|
541
|
+
+ ' <value name="ATTR">'
|
|
542
|
+
+ ' </value>'
|
|
543
|
+
+ '</block>';
|
|
544
|
+
|
|
545
|
+
Blockly.Blocks['file_data'] = {
|
|
546
|
+
/**
|
|
547
|
+
* Block for conditionally returning a value from a procedure.
|
|
548
|
+
* @this Blockly.Block
|
|
549
|
+
*/
|
|
550
|
+
init: function() {
|
|
551
|
+
this.appendDummyInput()
|
|
552
|
+
.appendField('📁');
|
|
553
|
+
|
|
554
|
+
this.appendDummyInput('ATTR')
|
|
555
|
+
.appendField(new Blockly.FieldDropdown([
|
|
556
|
+
[Blockly.Translate('file_data_data'), 'data'],
|
|
557
|
+
[Blockly.Translate('file_data_mimeType'), 'mimeType'],
|
|
558
|
+
]), 'ATTR');
|
|
559
|
+
|
|
560
|
+
this.setInputsInline(true);
|
|
561
|
+
this.setOutput(true);
|
|
562
|
+
this.setColour(Blockly.Action.HUE);
|
|
563
|
+
this.setTooltip(Blockly.Translate('file_data_tooltip'));
|
|
564
|
+
//this.setHelpUrl(getHelp('file_data'));
|
|
565
|
+
},
|
|
566
|
+
/**
|
|
567
|
+
* Called whenever anything on the workspace changes.
|
|
568
|
+
* Add warning if this flow block is not nested inside a loop.
|
|
569
|
+
* @param {!Blockly.Events.Abstract} e Change event.
|
|
570
|
+
* @this Blockly.Block
|
|
571
|
+
*/
|
|
572
|
+
onchange: function(e) {
|
|
573
|
+
let legal = false;
|
|
574
|
+
// Is the block nested in a trigger?
|
|
575
|
+
let block = this;
|
|
576
|
+
do {
|
|
577
|
+
if (this.FUNCTION_TYPES.includes(block.type)) {
|
|
578
|
+
legal = true;
|
|
579
|
+
break;
|
|
580
|
+
}
|
|
581
|
+
block = block.getSurroundParent();
|
|
582
|
+
} while (block);
|
|
583
|
+
|
|
584
|
+
if (legal) {
|
|
585
|
+
this.setWarningText(null, this.id);
|
|
586
|
+
} else {
|
|
587
|
+
this.setWarningText(Blockly.Translate('file_data_warning'), this.id);
|
|
588
|
+
}
|
|
589
|
+
},
|
|
590
|
+
/**
|
|
591
|
+
* List of block types that are functions and thus do not need warnings.
|
|
592
|
+
* To add a new function type add this to your code:
|
|
593
|
+
* Blockly.Blocks['procedures_ifreturn'].FUNCTION_TYPES.push('custom_func');
|
|
594
|
+
*/
|
|
595
|
+
FUNCTION_TYPES: ['file_read'],
|
|
596
|
+
};
|
|
597
|
+
Blockly.JavaScript['file_data'] = function(block) {
|
|
598
|
+
const attr = block.getFieldValue('ATTR');
|
|
599
|
+
|
|
600
|
+
return [attr, Blockly.JavaScript.ORDER_ATOMIC];
|
|
601
|
+
};
|
|
602
|
+
|
|
320
603
|
// --- action request --------------------------------------------------
|
|
321
604
|
Blockly.Action.blocks['request'] =
|
|
322
605
|
'<block type="request">'
|
|
@@ -403,7 +686,7 @@ Blockly.JavaScript['request'] = function(block) {
|
|
|
403
686
|
logText = '';
|
|
404
687
|
}
|
|
405
688
|
|
|
406
|
-
logText += `console.warn('request blockly block is deprecated - please use "http
|
|
689
|
+
logText += `console.warn('request blockly block is deprecated - please use "http (GET)" instead');\n`;
|
|
407
690
|
|
|
408
691
|
if (withStatement === 'TRUE' || withStatement === 'true' || withStatement === true) {
|
|
409
692
|
const statement = Blockly.JavaScript.statementToCode(block, 'STATEMENT');
|
|
@@ -229,7 +229,7 @@ Blockly.JavaScript['object_new'] = function(block) {
|
|
|
229
229
|
for (let n = 0; n < block.itemCount_; n++) {
|
|
230
230
|
const val = Blockly.JavaScript.valueToCode(block, 'ATTR_' + n, Blockly.JavaScript.ORDER_COMMA);
|
|
231
231
|
if (val) {
|
|
232
|
-
attributes.push(`'${block.attributes_[n]}': ${val}`);
|
|
232
|
+
attributes.push(`'${String(block.attributes_[n]).replaceAll(`'`, `\\'`)}': ${val}`);
|
|
233
233
|
}
|
|
234
234
|
}
|
|
235
235
|
|
|
@@ -282,7 +282,7 @@ Blockly.JavaScript['object_set_attr'] = function(block) {
|
|
|
282
282
|
obj = '{}';
|
|
283
283
|
}
|
|
284
284
|
|
|
285
|
-
return `(() => {
|
|
285
|
+
return `((obj) => { if (typeof obj === 'object') { obj['${attr}'] = ${value}; } })(${obj});\n`;
|
|
286
286
|
};
|
|
287
287
|
|
|
288
288
|
// --- delete attribute --------------------------------------------------
|
|
@@ -321,7 +321,7 @@ Blockly.JavaScript['object_del_attr'] = function(block) {
|
|
|
321
321
|
obj = '{}';
|
|
322
322
|
}
|
|
323
323
|
|
|
324
|
-
return `(() => {
|
|
324
|
+
return `((obj) => { if (typeof obj === 'object') { delete obj['${attr}']; } })(${obj});\n`;
|
|
325
325
|
};
|
|
326
326
|
|
|
327
327
|
// --- has attribute --------------------------------------------------
|
|
@@ -102,7 +102,7 @@ Blockly.Blocks['control'] = {
|
|
|
102
102
|
.appendField(Blockly.Translate('control'));
|
|
103
103
|
|
|
104
104
|
this.appendDummyInput('OID')
|
|
105
|
-
.appendField(new Blockly.FieldOID('
|
|
105
|
+
.appendField(new Blockly.FieldOID(Blockly.Translate('select_id'), 'state'), 'OID');
|
|
106
106
|
|
|
107
107
|
this.appendValueInput('VALUE')
|
|
108
108
|
.setCheck(null)
|
|
@@ -222,7 +222,7 @@ Blockly.Blocks['toggle'] = {
|
|
|
222
222
|
.appendField(Blockly.Translate('toggle'));
|
|
223
223
|
|
|
224
224
|
this.appendDummyInput('OID')
|
|
225
|
-
.appendField(new Blockly.FieldOID('
|
|
225
|
+
.appendField(new Blockly.FieldOID(Blockly.Translate('select_id'), 'state'), 'OID');
|
|
226
226
|
|
|
227
227
|
this.appendDummyInput('WITH_DELAY')
|
|
228
228
|
.appendField(Blockly.Translate('toggle_delay'))
|
|
@@ -362,7 +362,7 @@ Blockly.Blocks['update'] = {
|
|
|
362
362
|
.appendField(Blockly.Translate('update'));
|
|
363
363
|
|
|
364
364
|
this.appendDummyInput('OID')
|
|
365
|
-
.appendField(new Blockly.FieldOID('
|
|
365
|
+
.appendField(new Blockly.FieldOID(Blockly.Translate('select_id'), 'state'), 'OID');
|
|
366
366
|
|
|
367
367
|
this.appendValueInput('VALUE')
|
|
368
368
|
.setCheck(null)
|
|
@@ -775,7 +775,6 @@ Blockly.Blocks['get_value'] = {
|
|
|
775
775
|
[Blockly.Translate('get_common_unit'), 'common.unit'],
|
|
776
776
|
[Blockly.Translate('get_common_role'), 'common.role'],
|
|
777
777
|
[Blockly.Translate('get_common_state_type'), 'common.type'],
|
|
778
|
-
[Blockly.Translate('get_common_object_type'), 'type'],
|
|
779
778
|
[Blockly.Translate('get_common_read'), 'common.read'],
|
|
780
779
|
[Blockly.Translate('get_common_write'), 'common.write'],
|
|
781
780
|
]), 'ATTR');
|
|
@@ -784,7 +783,7 @@ Blockly.Blocks['get_value'] = {
|
|
|
784
783
|
.appendField(Blockly.Translate('get_value_OID'));
|
|
785
784
|
|
|
786
785
|
this.appendDummyInput()
|
|
787
|
-
.appendField(new Blockly.FieldOID(Blockly.Translate('
|
|
786
|
+
.appendField(new Blockly.FieldOID(Blockly.Translate('select_id'), 'state'), 'OID');
|
|
788
787
|
|
|
789
788
|
this.setInputsInline(true);
|
|
790
789
|
this.setOutput(true);
|
|
@@ -849,7 +848,6 @@ Blockly.Blocks['get_value_var'] = {
|
|
|
849
848
|
[Blockly.Translate('get_common_unit'), 'common.unit'],
|
|
850
849
|
[Blockly.Translate('get_common_role'), 'common.role'],
|
|
851
850
|
[Blockly.Translate('get_common_state_type'), 'common.type'],
|
|
852
|
-
[Blockly.Translate('get_common_object_type'), 'type'],
|
|
853
851
|
[Blockly.Translate('get_common_read'), 'common.read'],
|
|
854
852
|
[Blockly.Translate('get_common_write'), 'common.write'],
|
|
855
853
|
]), 'ATTR');
|
|
@@ -922,7 +920,6 @@ Blockly.Blocks['get_value_async'] = {
|
|
|
922
920
|
[Blockly.Translate('get_common_unit'), 'common.unit'],
|
|
923
921
|
[Blockly.Translate('get_common_role'), 'common.role'],
|
|
924
922
|
[Blockly.Translate('get_common_state_type'), 'common.type'],
|
|
925
|
-
[Blockly.Translate('get_common_object_type'), 'type'],
|
|
926
923
|
[Blockly.Translate('get_common_read'), 'common.read'],
|
|
927
924
|
[Blockly.Translate('get_common_write'), 'common.write'],
|
|
928
925
|
]), 'ATTR');
|
|
@@ -931,7 +928,7 @@ Blockly.Blocks['get_value_async'] = {
|
|
|
931
928
|
.appendField(Blockly.Translate('get_value_OID'));
|
|
932
929
|
|
|
933
930
|
this.appendDummyInput()
|
|
934
|
-
.appendField(new Blockly.FieldOID(Blockly.Translate('
|
|
931
|
+
.appendField(new Blockly.FieldOID(Blockly.Translate('select_id'), 'state'), 'OID');
|
|
935
932
|
|
|
936
933
|
this.appendStatementInput('STATEMENT')
|
|
937
934
|
.setCheck(null);
|
|
@@ -978,7 +975,7 @@ Blockly.Blocks['get_object'] = {
|
|
|
978
975
|
.appendField(Blockly.Translate('get_object'));
|
|
979
976
|
|
|
980
977
|
this.appendDummyInput()
|
|
981
|
-
.appendField(new Blockly.FieldOID(Blockly.Translate('
|
|
978
|
+
.appendField(new Blockly.FieldOID(Blockly.Translate('select_id'), 'all'), 'OID');
|
|
982
979
|
|
|
983
980
|
this.setInputsInline(true);
|
|
984
981
|
this.setOutput(true);
|
|
@@ -1024,7 +1021,7 @@ Blockly.Blocks['get_object_async'] = {
|
|
|
1024
1021
|
.appendField(Blockly.Translate('get_object'));
|
|
1025
1022
|
|
|
1026
1023
|
this.appendDummyInput()
|
|
1027
|
-
.appendField(new Blockly.FieldOID(Blockly.Translate('
|
|
1024
|
+
.appendField(new Blockly.FieldOID(Blockly.Translate('select_id'), 'all'), 'OID');
|
|
1028
1025
|
|
|
1029
1026
|
this.appendStatementInput('STATEMENT')
|
|
1030
1027
|
.setCheck(null);
|
|
@@ -1061,7 +1058,7 @@ Blockly.Blocks['field_oid'] = {
|
|
|
1061
1058
|
.appendField(Blockly.Translate('field_oid_OID'));
|
|
1062
1059
|
|
|
1063
1060
|
this.appendDummyInput()
|
|
1064
|
-
.appendField(new Blockly.FieldOID('
|
|
1061
|
+
.appendField(new Blockly.FieldOID(Blockly.Translate('select_id'), 'state'), 'oid');
|
|
1065
1062
|
|
|
1066
1063
|
this.setInputsInline(true);
|
|
1067
1064
|
this.setColour("%{BKY_TEXTS_HUE}");
|
|
@@ -1089,7 +1086,7 @@ Blockly.Blocks['field_oid_meta'] = {
|
|
|
1089
1086
|
.appendField(Blockly.Translate('field_oid_OID_meta'));
|
|
1090
1087
|
|
|
1091
1088
|
this.appendDummyInput()
|
|
1092
|
-
.appendField(new Blockly.FieldOID('
|
|
1089
|
+
.appendField(new Blockly.FieldOID(Blockly.Translate('select_id'), 'meta'), 'oid');
|
|
1093
1090
|
|
|
1094
1091
|
this.setInputsInline(true);
|
|
1095
1092
|
this.setColour("%{BKY_TEXTS_HUE}");
|
|
@@ -1117,7 +1114,7 @@ Blockly.Blocks['field_oid_script'] = {
|
|
|
1117
1114
|
.appendField(Blockly.Translate('field_oid_OID_script'));
|
|
1118
1115
|
|
|
1119
1116
|
this.appendDummyInput()
|
|
1120
|
-
.appendField(new Blockly.FieldOID('
|
|
1117
|
+
.appendField(new Blockly.FieldOID(Blockly.Translate('select_id'), 'script'), 'oid');
|
|
1121
1118
|
|
|
1122
1119
|
this.setInputsInline(true);
|
|
1123
1120
|
this.setColour("%{BKY_TEXTS_HUE}");
|