node-red-contrib-questdb 0.2.0 → 0.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.
@@ -0,0 +1,924 @@
1
+ [
2
+ {
3
+ "id": "questdb-examples-tab",
4
+ "type": "tab",
5
+ "label": "QuestDB Examples",
6
+ "disabled": false,
7
+ "info": "Complete examples for node-red-contrib-questdb.\nMake sure QuestDB is running on localhost:9000 before testing."
8
+ },
9
+ {
10
+ "id": "comment-header",
11
+ "type": "comment",
12
+ "z": "questdb-examples-tab",
13
+ "name": "=== QuestDB Node-RED Examples ===",
14
+ "info": "Comprehensive examples covering all features.\nClick inject nodes to test each scenario.",
15
+ "x": 200,
16
+ "y": 40
17
+ },
18
+ {
19
+ "id": "comment-basic",
20
+ "type": "comment",
21
+ "z": "questdb-examples-tab",
22
+ "name": "--- Basic Examples ---",
23
+ "info": "",
24
+ "x": 140,
25
+ "y": 100
26
+ },
27
+ {
28
+ "id": "inject-direct",
29
+ "type": "inject",
30
+ "z": "questdb-examples-tab",
31
+ "name": "Structured data",
32
+ "props": [
33
+ {"p": "topic", "vt": "str"},
34
+ {"p": "payload"}
35
+ ],
36
+ "repeat": "",
37
+ "crontab": "",
38
+ "once": false,
39
+ "onceDelay": 0.1,
40
+ "topic": "sensors",
41
+ "payload": "{}",
42
+ "payloadType": "json",
43
+ "x": 150,
44
+ "y": 160,
45
+ "wires": [["function-basic"]]
46
+ },
47
+ {
48
+ "id": "function-basic",
49
+ "type": "function",
50
+ "z": "questdb-examples-tab",
51
+ "name": "Basic sensor data",
52
+ "func": "msg.payload = {\n symbols: {\n device_id: \"sensor_001\",\n location: \"warehouse\"\n },\n columns: {\n temperature: 23.5,\n humidity: 65.2,\n pressure: 1013.25\n },\n timestamp: Date.now()\n};\nreturn msg;",
53
+ "outputs": 1,
54
+ "x": 360,
55
+ "y": 160,
56
+ "wires": [["questdb-write-basic"]]
57
+ },
58
+ {
59
+ "id": "questdb-write-basic",
60
+ "type": "questdb",
61
+ "z": "questdb-examples-tab",
62
+ "name": "Write to QuestDB",
63
+ "questdb": "questdb-config-examples",
64
+ "autoFlush": true,
65
+ "flushInterval": 1000,
66
+ "x": 570,
67
+ "y": 160,
68
+ "wires": [["debug-basic"]]
69
+ },
70
+ {
71
+ "id": "debug-basic",
72
+ "type": "debug",
73
+ "z": "questdb-examples-tab",
74
+ "name": "Result",
75
+ "active": true,
76
+ "tosidebar": true,
77
+ "console": false,
78
+ "tostatus": true,
79
+ "complete": "payload",
80
+ "targetType": "msg",
81
+ "statusVal": "payload.success",
82
+ "statusType": "auto",
83
+ "x": 750,
84
+ "y": 160
85
+ },
86
+ {
87
+ "id": "inject-simple",
88
+ "type": "inject",
89
+ "z": "questdb-examples-tab",
90
+ "name": "Simple numeric value",
91
+ "props": [
92
+ {"p": "payload"},
93
+ {"p": "topic", "vt": "str"}
94
+ ],
95
+ "repeat": "",
96
+ "crontab": "",
97
+ "once": false,
98
+ "onceDelay": 0.1,
99
+ "topic": "cpu_usage",
100
+ "payload": "45.7",
101
+ "payloadType": "num",
102
+ "x": 170,
103
+ "y": 220,
104
+ "wires": [["questdb-write-basic"]]
105
+ },
106
+ {
107
+ "id": "comment-types",
108
+ "type": "comment",
109
+ "z": "questdb-examples-tab",
110
+ "name": "--- Explicit Column Types (int, long, double, decimal) ---",
111
+ "info": "",
112
+ "x": 240,
113
+ "y": 300
114
+ },
115
+ {
116
+ "id": "inject-explicit-types",
117
+ "type": "inject",
118
+ "z": "questdb-examples-tab",
119
+ "name": "Explicit types",
120
+ "props": [
121
+ {"p": "payload"},
122
+ {"p": "topic", "vt": "str"}
123
+ ],
124
+ "repeat": "",
125
+ "crontab": "",
126
+ "once": false,
127
+ "onceDelay": 0.1,
128
+ "topic": "typed_data",
129
+ "payload": "{}",
130
+ "payloadType": "json",
131
+ "x": 150,
132
+ "y": 360,
133
+ "wires": [["function-explicit-types"]]
134
+ },
135
+ {
136
+ "id": "function-explicit-types",
137
+ "type": "function",
138
+ "z": "questdb-examples-tab",
139
+ "name": "Explicit type specification",
140
+ "func": "msg.payload = {\n symbols: {\n device_id: \"sensor_001\"\n },\n columns: {\n // Explicit integer (32-bit)\n count: { value: 42, type: 'int' },\n \n // Explicit long (64-bit)\n total_bytes: { value: 9876543210, type: 'long' },\n \n // Explicit float (32-bit)\n temperature: { value: 23.456, type: 'float' },\n \n // Explicit double (64-bit, higher precision)\n precise_value: { value: 3.141592653589793, type: 'double' },\n \n // Decimal (arbitrary precision)\n price: { value: '123.45', type: 'decimal' },\n \n // Decimal with mantissa and scale\n exact_amount: { mantissa: 12345, scale: 2, type: 'decimal' },\n \n // Auto-detected types (default behavior)\n auto_number: 100.5,\n auto_string: \"hello\",\n auto_boolean: true\n },\n timestamp: Date.now()\n};\nreturn msg;",
141
+ "outputs": 1,
142
+ "x": 400,
143
+ "y": 360,
144
+ "wires": [["questdb-write-types", "debug-types"]]
145
+ },
146
+ {
147
+ "id": "questdb-write-types",
148
+ "type": "questdb",
149
+ "z": "questdb-examples-tab",
150
+ "name": "Write typed data",
151
+ "questdb": "questdb-config-examples",
152
+ "autoFlush": true,
153
+ "flushInterval": 1000,
154
+ "x": 630,
155
+ "y": 360,
156
+ "wires": [["debug-types-result"]]
157
+ },
158
+ {
159
+ "id": "debug-types",
160
+ "type": "debug",
161
+ "z": "questdb-examples-tab",
162
+ "name": "Payload",
163
+ "active": true,
164
+ "tosidebar": true,
165
+ "console": false,
166
+ "tostatus": false,
167
+ "complete": "payload",
168
+ "targetType": "msg",
169
+ "x": 630,
170
+ "y": 320
171
+ },
172
+ {
173
+ "id": "debug-types-result",
174
+ "type": "debug",
175
+ "z": "questdb-examples-tab",
176
+ "name": "Result",
177
+ "active": true,
178
+ "tosidebar": true,
179
+ "console": false,
180
+ "tostatus": true,
181
+ "complete": "payload",
182
+ "targetType": "msg",
183
+ "statusVal": "payload.success",
184
+ "statusType": "auto",
185
+ "x": 830,
186
+ "y": 360
187
+ },
188
+ {
189
+ "id": "comment-arrays",
190
+ "type": "comment",
191
+ "z": "questdb-examples-tab",
192
+ "name": "--- Array Columns ---",
193
+ "info": "",
194
+ "x": 150,
195
+ "y": 440
196
+ },
197
+ {
198
+ "id": "inject-arrays",
199
+ "type": "inject",
200
+ "z": "questdb-examples-tab",
201
+ "name": "Array data",
202
+ "props": [
203
+ {"p": "payload"},
204
+ {"p": "topic", "vt": "str"}
205
+ ],
206
+ "repeat": "",
207
+ "crontab": "",
208
+ "once": false,
209
+ "onceDelay": 0.1,
210
+ "topic": "array_data",
211
+ "payload": "{}",
212
+ "payloadType": "json",
213
+ "x": 140,
214
+ "y": 500,
215
+ "wires": [["function-arrays"]]
216
+ },
217
+ {
218
+ "id": "function-arrays",
219
+ "type": "function",
220
+ "z": "questdb-examples-tab",
221
+ "name": "Array columns",
222
+ "func": "msg.payload = {\n symbols: {\n sensor_id: \"multi_sensor_001\"\n },\n columns: {\n // Auto-detected array (elements determine type)\n readings: [1.5, 2.3, 3.7, 4.1, 5.9],\n \n // Explicit double array\n temperatures: { \n value: [22.1, 23.4, 21.8, 24.2], \n type: 'array', \n elementType: 'double' \n },\n \n // Explicit long array\n timestamps_micro: { \n value: [1704067200000000, 1704067260000000, 1704067320000000], \n type: 'array', \n elementType: 'long' \n },\n \n // String array\n tags: [\"critical\", \"production\", \"monitored\"],\n \n // Boolean array\n flags: [true, false, true, true]\n },\n timestamp: Date.now()\n};\nreturn msg;",
223
+ "outputs": 1,
224
+ "x": 350,
225
+ "y": 500,
226
+ "wires": [["questdb-write-arrays", "debug-arrays"]]
227
+ },
228
+ {
229
+ "id": "questdb-write-arrays",
230
+ "type": "questdb",
231
+ "z": "questdb-examples-tab",
232
+ "name": "Write arrays",
233
+ "questdb": "questdb-config-examples",
234
+ "autoFlush": true,
235
+ "flushInterval": 1000,
236
+ "x": 560,
237
+ "y": 500,
238
+ "wires": [["debug-arrays-result"]]
239
+ },
240
+ {
241
+ "id": "debug-arrays",
242
+ "type": "debug",
243
+ "z": "questdb-examples-tab",
244
+ "name": "Array payload",
245
+ "active": true,
246
+ "tosidebar": true,
247
+ "console": false,
248
+ "tostatus": false,
249
+ "complete": "payload",
250
+ "targetType": "msg",
251
+ "x": 570,
252
+ "y": 460
253
+ },
254
+ {
255
+ "id": "debug-arrays-result",
256
+ "type": "debug",
257
+ "z": "questdb-examples-tab",
258
+ "name": "Result",
259
+ "active": true,
260
+ "tosidebar": true,
261
+ "console": false,
262
+ "tostatus": true,
263
+ "complete": "payload",
264
+ "targetType": "msg",
265
+ "statusVal": "payload.success",
266
+ "statusType": "auto",
267
+ "x": 750,
268
+ "y": 500
269
+ },
270
+ {
271
+ "id": "inject-time-series-array",
272
+ "type": "inject",
273
+ "z": "questdb-examples-tab",
274
+ "name": "Time series batch",
275
+ "props": [
276
+ {"p": "payload"},
277
+ {"p": "topic", "vt": "str"}
278
+ ],
279
+ "repeat": "",
280
+ "crontab": "",
281
+ "once": false,
282
+ "onceDelay": 0.1,
283
+ "topic": "batch_readings",
284
+ "payload": "{}",
285
+ "payloadType": "json",
286
+ "x": 160,
287
+ "y": 560,
288
+ "wires": [["function-time-series"]]
289
+ },
290
+ {
291
+ "id": "function-time-series",
292
+ "type": "function",
293
+ "z": "questdb-examples-tab",
294
+ "name": "Multiple readings as arrays",
295
+ "func": "// Store multiple readings from a sampling window\nmsg.payload = {\n symbols: {\n device_id: \"vibration_sensor_001\",\n location: \"motor_housing\"\n },\n columns: {\n // 100 samples at 1kHz for vibration analysis\n x_axis: Array.from({length: 100}, () => (Math.random() - 0.5) * 10),\n y_axis: Array.from({length: 100}, () => (Math.random() - 0.5) * 10),\n z_axis: Array.from({length: 100}, () => (Math.random() - 0.5) * 10),\n \n // FFT frequency bins\n fft_magnitudes: { \n value: Array.from({length: 50}, () => Math.random() * 100),\n type: 'array',\n elementType: 'double'\n },\n \n // Statistics\n sample_count: { value: 100, type: 'int' },\n sample_rate_hz: { value: 1000, type: 'int' }\n },\n timestamp: Date.now()\n};\nreturn msg;",
296
+ "outputs": 1,
297
+ "x": 410,
298
+ "y": 560,
299
+ "wires": [["questdb-write-arrays"]]
300
+ },
301
+ {
302
+ "id": "comment-timestamps",
303
+ "type": "comment",
304
+ "z": "questdb-examples-tab",
305
+ "name": "--- Timestamp Formats ---",
306
+ "info": "",
307
+ "x": 160,
308
+ "y": 640
309
+ },
310
+ {
311
+ "id": "inject-ts-ms",
312
+ "type": "inject",
313
+ "z": "questdb-examples-tab",
314
+ "name": "Milliseconds",
315
+ "props": [
316
+ {"p": "payload"},
317
+ {"p": "topic", "vt": "str"}
318
+ ],
319
+ "repeat": "",
320
+ "crontab": "",
321
+ "once": false,
322
+ "onceDelay": 0.1,
323
+ "topic": "timestamp_test",
324
+ "payload": "{}",
325
+ "payloadType": "json",
326
+ "x": 150,
327
+ "y": 700,
328
+ "wires": [["function-ts-ms"]]
329
+ },
330
+ {
331
+ "id": "function-ts-ms",
332
+ "type": "function",
333
+ "z": "questdb-examples-tab",
334
+ "name": "Epoch milliseconds",
335
+ "func": "msg.payload = {\n symbols: { format: \"milliseconds\" },\n columns: { value: 100 },\n timestamp: Date.now()\n};\nreturn msg;",
336
+ "outputs": 1,
337
+ "x": 370,
338
+ "y": 700,
339
+ "wires": [["questdb-write-ts"]]
340
+ },
341
+ {
342
+ "id": "inject-ts-iso",
343
+ "type": "inject",
344
+ "z": "questdb-examples-tab",
345
+ "name": "ISO string",
346
+ "props": [
347
+ {"p": "payload"},
348
+ {"p": "topic", "vt": "str"}
349
+ ],
350
+ "repeat": "",
351
+ "crontab": "",
352
+ "once": false,
353
+ "onceDelay": 0.1,
354
+ "topic": "timestamp_test",
355
+ "payload": "{}",
356
+ "payloadType": "json",
357
+ "x": 140,
358
+ "y": 740,
359
+ "wires": [["function-ts-iso"]]
360
+ },
361
+ {
362
+ "id": "function-ts-iso",
363
+ "type": "function",
364
+ "z": "questdb-examples-tab",
365
+ "name": "ISO 8601 string",
366
+ "func": "msg.payload = {\n symbols: { format: \"iso_string\" },\n columns: { value: 200 },\n timestamp: new Date().toISOString()\n};\nreturn msg;",
367
+ "outputs": 1,
368
+ "x": 370,
369
+ "y": 740,
370
+ "wires": [["questdb-write-ts"]]
371
+ },
372
+ {
373
+ "id": "inject-ts-date",
374
+ "type": "inject",
375
+ "z": "questdb-examples-tab",
376
+ "name": "Date object",
377
+ "props": [
378
+ {"p": "payload"},
379
+ {"p": "topic", "vt": "str"}
380
+ ],
381
+ "repeat": "",
382
+ "crontab": "",
383
+ "once": false,
384
+ "onceDelay": 0.1,
385
+ "topic": "timestamp_test",
386
+ "payload": "{}",
387
+ "payloadType": "json",
388
+ "x": 140,
389
+ "y": 780,
390
+ "wires": [["function-ts-date"]]
391
+ },
392
+ {
393
+ "id": "function-ts-date",
394
+ "type": "function",
395
+ "z": "questdb-examples-tab",
396
+ "name": "Date object",
397
+ "func": "msg.payload = {\n symbols: { format: \"date_object\" },\n columns: { value: 300 },\n timestamp: new Date()\n};\nreturn msg;",
398
+ "outputs": 1,
399
+ "x": 360,
400
+ "y": 780,
401
+ "wires": [["questdb-write-ts"]]
402
+ },
403
+ {
404
+ "id": "inject-ts-auto",
405
+ "type": "inject",
406
+ "z": "questdb-examples-tab",
407
+ "name": "Auto (server time)",
408
+ "props": [
409
+ {"p": "payload"},
410
+ {"p": "topic", "vt": "str"}
411
+ ],
412
+ "repeat": "",
413
+ "crontab": "",
414
+ "once": false,
415
+ "onceDelay": 0.1,
416
+ "topic": "timestamp_test",
417
+ "payload": "{}",
418
+ "payloadType": "json",
419
+ "x": 160,
420
+ "y": 820,
421
+ "wires": [["function-ts-auto"]]
422
+ },
423
+ {
424
+ "id": "function-ts-auto",
425
+ "type": "function",
426
+ "z": "questdb-examples-tab",
427
+ "name": "No timestamp",
428
+ "func": "msg.payload = {\n symbols: { format: \"auto_now\" },\n columns: { value: 400 }\n // No timestamp - uses server time\n};\nreturn msg;",
429
+ "outputs": 1,
430
+ "x": 370,
431
+ "y": 820,
432
+ "wires": [["questdb-write-ts"]]
433
+ },
434
+ {
435
+ "id": "questdb-write-ts",
436
+ "type": "questdb",
437
+ "z": "questdb-examples-tab",
438
+ "name": "Write",
439
+ "questdb": "questdb-config-examples",
440
+ "autoFlush": true,
441
+ "flushInterval": 1000,
442
+ "x": 550,
443
+ "y": 760,
444
+ "wires": [["debug-ts-result"]]
445
+ },
446
+ {
447
+ "id": "debug-ts-result",
448
+ "type": "debug",
449
+ "z": "questdb-examples-tab",
450
+ "name": "Result",
451
+ "active": true,
452
+ "tosidebar": true,
453
+ "console": false,
454
+ "tostatus": true,
455
+ "complete": "payload",
456
+ "targetType": "msg",
457
+ "statusVal": "payload.success",
458
+ "statusType": "auto",
459
+ "x": 710,
460
+ "y": 760
461
+ },
462
+ {
463
+ "id": "comment-mapper",
464
+ "type": "comment",
465
+ "z": "questdb-examples-tab",
466
+ "name": "--- Mapper Node Examples ---",
467
+ "info": "",
468
+ "x": 170,
469
+ "y": 900
470
+ },
471
+ {
472
+ "id": "inject-mapper-basic",
473
+ "type": "inject",
474
+ "z": "questdb-examples-tab",
475
+ "name": "Raw sensor data",
476
+ "props": [
477
+ {"p": "payload"},
478
+ {"p": "topic", "vt": "str"}
479
+ ],
480
+ "repeat": "",
481
+ "crontab": "",
482
+ "once": false,
483
+ "onceDelay": 0.1,
484
+ "topic": "raw_reading",
485
+ "payload": "{\"device\":\"temp_sensor_01\",\"reading\":22.7,\"battery\":85,\"ts\":0}",
486
+ "payloadType": "json",
487
+ "x": 160,
488
+ "y": 960,
489
+ "wires": [["function-mapper-ts"]]
490
+ },
491
+ {
492
+ "id": "function-mapper-ts",
493
+ "type": "function",
494
+ "z": "questdb-examples-tab",
495
+ "name": "Add timestamp",
496
+ "func": "msg.payload.ts = Date.now();\nreturn msg;",
497
+ "outputs": 1,
498
+ "x": 360,
499
+ "y": 960,
500
+ "wires": [["mapper-basic"]]
501
+ },
502
+ {
503
+ "id": "mapper-basic",
504
+ "type": "questdb-mapper",
505
+ "z": "questdb-examples-tab",
506
+ "name": "Map to ILP",
507
+ "tableName": "temperature_readings",
508
+ "timestampField": "payload.ts",
509
+ "symbolMappings": [
510
+ {"source": "payload.device", "target": "device_id"}
511
+ ],
512
+ "columnMappings": [
513
+ {"source": "payload.reading", "target": "temperature", "type": "double"},
514
+ {"source": "payload.battery", "target": "battery_level", "type": "integer"}
515
+ ],
516
+ "x": 550,
517
+ "y": 960,
518
+ "wires": [["debug-mapper-out", "questdb-write-mapper"]]
519
+ },
520
+ {
521
+ "id": "debug-mapper-out",
522
+ "type": "debug",
523
+ "z": "questdb-examples-tab",
524
+ "name": "Mapped output",
525
+ "active": true,
526
+ "tosidebar": true,
527
+ "console": false,
528
+ "tostatus": false,
529
+ "complete": "true",
530
+ "targetType": "full",
531
+ "x": 760,
532
+ "y": 920
533
+ },
534
+ {
535
+ "id": "questdb-write-mapper",
536
+ "type": "questdb",
537
+ "z": "questdb-examples-tab",
538
+ "name": "Write mapped",
539
+ "questdb": "questdb-config-examples",
540
+ "autoFlush": true,
541
+ "flushInterval": 1000,
542
+ "x": 760,
543
+ "y": 960,
544
+ "wires": [["debug-mapper-result"]]
545
+ },
546
+ {
547
+ "id": "debug-mapper-result",
548
+ "type": "debug",
549
+ "z": "questdb-examples-tab",
550
+ "name": "Result",
551
+ "active": true,
552
+ "tosidebar": true,
553
+ "console": false,
554
+ "tostatus": true,
555
+ "complete": "payload",
556
+ "targetType": "msg",
557
+ "statusVal": "payload.success",
558
+ "statusType": "auto",
559
+ "x": 950,
560
+ "y": 960
561
+ },
562
+ {
563
+ "id": "inject-mapper-arrays",
564
+ "type": "inject",
565
+ "z": "questdb-examples-tab",
566
+ "name": "Data with arrays",
567
+ "props": [
568
+ {"p": "payload"},
569
+ {"p": "topic", "vt": "str"}
570
+ ],
571
+ "repeat": "",
572
+ "crontab": "",
573
+ "once": false,
574
+ "onceDelay": 0.1,
575
+ "topic": "array_reading",
576
+ "payload": "{\"sensor\":\"multi_01\",\"values\":[1.1,2.2,3.3,4.4],\"labels\":[\"a\",\"b\",\"c\"],\"ts\":0}",
577
+ "payloadType": "json",
578
+ "x": 160,
579
+ "y": 1020,
580
+ "wires": [["function-mapper-arrays-ts"]]
581
+ },
582
+ {
583
+ "id": "function-mapper-arrays-ts",
584
+ "type": "function",
585
+ "z": "questdb-examples-tab",
586
+ "name": "Add timestamp",
587
+ "func": "msg.payload.ts = Date.now();\nreturn msg;",
588
+ "outputs": 1,
589
+ "x": 360,
590
+ "y": 1020,
591
+ "wires": [["mapper-arrays"]]
592
+ },
593
+ {
594
+ "id": "mapper-arrays",
595
+ "type": "questdb-mapper",
596
+ "z": "questdb-examples-tab",
597
+ "name": "Map arrays",
598
+ "tableName": "array_readings",
599
+ "timestampField": "payload.ts",
600
+ "symbolMappings": [
601
+ {"source": "payload.sensor", "target": "sensor_id"}
602
+ ],
603
+ "columnMappings": [
604
+ {"source": "payload.values", "target": "measurements", "type": "array_double"},
605
+ {"source": "payload.labels", "target": "tags", "type": "array_string"}
606
+ ],
607
+ "x": 550,
608
+ "y": 1020,
609
+ "wires": [["debug-mapper-out", "questdb-write-mapper"]]
610
+ },
611
+ {
612
+ "id": "comment-iot",
613
+ "type": "comment",
614
+ "z": "questdb-examples-tab",
615
+ "name": "--- IoT Protocol Examples ---",
616
+ "info": "",
617
+ "x": 170,
618
+ "y": 1100
619
+ },
620
+ {
621
+ "id": "inject-mqtt",
622
+ "type": "inject",
623
+ "z": "questdb-examples-tab",
624
+ "name": "MQTT-style message",
625
+ "props": [
626
+ {"p": "payload"},
627
+ {"p": "topic", "vt": "str"}
628
+ ],
629
+ "repeat": "",
630
+ "crontab": "",
631
+ "once": false,
632
+ "onceDelay": 0.1,
633
+ "topic": "home/livingroom/temperature",
634
+ "payload": "22.5",
635
+ "payloadType": "num",
636
+ "x": 170,
637
+ "y": 1160,
638
+ "wires": [["function-mqtt"]]
639
+ },
640
+ {
641
+ "id": "function-mqtt",
642
+ "type": "function",
643
+ "z": "questdb-examples-tab",
644
+ "name": "Transform MQTT to ILP",
645
+ "func": "// Parse MQTT topic: home/livingroom/temperature\nconst parts = msg.topic.split('/');\nconst location = parts[1] || 'unknown';\nconst measurement = parts[2] || 'value';\n\nmsg.topic = 'mqtt_sensors';\nmsg.payload = {\n symbols: {\n location: location,\n measurement_type: measurement\n },\n columns: {\n value: msg.payload\n },\n timestamp: Date.now()\n};\nreturn msg;",
646
+ "outputs": 1,
647
+ "x": 410,
648
+ "y": 1160,
649
+ "wires": [["questdb-write-iot", "debug-iot"]]
650
+ },
651
+ {
652
+ "id": "inject-modbus",
653
+ "type": "inject",
654
+ "z": "questdb-examples-tab",
655
+ "name": "Modbus registers",
656
+ "props": [
657
+ {"p": "payload"},
658
+ {"p": "topic", "vt": "str"}
659
+ ],
660
+ "repeat": "",
661
+ "crontab": "",
662
+ "once": false,
663
+ "onceDelay": 0.1,
664
+ "topic": "plc_data",
665
+ "payload": "{\"unitId\":1,\"registers\":[100,200,300,400],\"address\":40001}",
666
+ "payloadType": "json",
667
+ "x": 160,
668
+ "y": 1220,
669
+ "wires": [["function-modbus"]]
670
+ },
671
+ {
672
+ "id": "function-modbus",
673
+ "type": "function",
674
+ "z": "questdb-examples-tab",
675
+ "name": "Transform Modbus to ILP",
676
+ "func": "const regs = msg.payload.registers;\nmsg.topic = 'modbus_data';\nmsg.payload = {\n symbols: {\n unit_id: String(msg.payload.unitId),\n base_address: String(msg.payload.address)\n },\n columns: {\n // Store registers as an array\n registers: regs,\n register_count: { value: regs.length, type: 'int' }\n },\n timestamp: Date.now()\n};\nreturn msg;",
677
+ "outputs": 1,
678
+ "x": 420,
679
+ "y": 1220,
680
+ "wires": [["questdb-write-iot", "debug-iot"]]
681
+ },
682
+ {
683
+ "id": "questdb-write-iot",
684
+ "type": "questdb",
685
+ "z": "questdb-examples-tab",
686
+ "name": "Write IoT data",
687
+ "questdb": "questdb-config-examples",
688
+ "autoFlush": true,
689
+ "flushInterval": 1000,
690
+ "x": 660,
691
+ "y": 1190,
692
+ "wires": [["debug-iot-result"]]
693
+ },
694
+ {
695
+ "id": "debug-iot",
696
+ "type": "debug",
697
+ "z": "questdb-examples-tab",
698
+ "name": "Transformed",
699
+ "active": true,
700
+ "tosidebar": true,
701
+ "console": false,
702
+ "tostatus": false,
703
+ "complete": "payload",
704
+ "targetType": "msg",
705
+ "x": 660,
706
+ "y": 1140
707
+ },
708
+ {
709
+ "id": "debug-iot-result",
710
+ "type": "debug",
711
+ "z": "questdb-examples-tab",
712
+ "name": "Result",
713
+ "active": true,
714
+ "tosidebar": true,
715
+ "console": false,
716
+ "tostatus": true,
717
+ "complete": "payload",
718
+ "targetType": "msg",
719
+ "statusVal": "payload.success",
720
+ "statusType": "auto",
721
+ "x": 850,
722
+ "y": 1190
723
+ },
724
+ {
725
+ "id": "comment-continuous",
726
+ "type": "comment",
727
+ "z": "questdb-examples-tab",
728
+ "name": "--- Continuous Data Generation ---",
729
+ "info": "",
730
+ "x": 190,
731
+ "y": 1300
732
+ },
733
+ {
734
+ "id": "inject-continuous",
735
+ "type": "inject",
736
+ "z": "questdb-examples-tab",
737
+ "name": "Every 1 second",
738
+ "props": [
739
+ {"p": "payload"},
740
+ {"p": "topic", "vt": "str"}
741
+ ],
742
+ "repeat": "1",
743
+ "crontab": "",
744
+ "once": false,
745
+ "onceDelay": 0.1,
746
+ "topic": "metrics",
747
+ "payload": "",
748
+ "payloadType": "date",
749
+ "x": 160,
750
+ "y": 1360,
751
+ "wires": [["function-continuous"]]
752
+ },
753
+ {
754
+ "id": "function-continuous",
755
+ "type": "function",
756
+ "z": "questdb-examples-tab",
757
+ "name": "Generate random metrics",
758
+ "func": "msg.payload = {\n symbols: {\n host: \"server-\" + Math.floor(Math.random() * 3 + 1),\n region: [\"us-east\", \"us-west\", \"eu-west\"][Math.floor(Math.random() * 3)]\n },\n columns: {\n cpu: Math.random() * 100,\n memory: Math.random() * 100,\n disk_io: { value: Math.random() * 1000, type: 'double' },\n connections: { value: Math.floor(Math.random() * 1000), type: 'int' },\n // Array of recent latencies\n latency_samples: Array.from({length: 10}, () => Math.random() * 100)\n },\n timestamp: Date.now()\n};\nreturn msg;",
759
+ "outputs": 1,
760
+ "x": 410,
761
+ "y": 1360,
762
+ "wires": [["questdb-write-continuous"]]
763
+ },
764
+ {
765
+ "id": "questdb-write-continuous",
766
+ "type": "questdb",
767
+ "z": "questdb-examples-tab",
768
+ "name": "Write metrics",
769
+ "questdb": "questdb-config-examples",
770
+ "autoFlush": true,
771
+ "flushInterval": 1000,
772
+ "x": 650,
773
+ "y": 1360,
774
+ "wires": [["debug-continuous"]]
775
+ },
776
+ {
777
+ "id": "debug-continuous",
778
+ "type": "debug",
779
+ "z": "questdb-examples-tab",
780
+ "name": "Result",
781
+ "active": false,
782
+ "tosidebar": true,
783
+ "console": false,
784
+ "tostatus": true,
785
+ "complete": "payload",
786
+ "targetType": "msg",
787
+ "statusVal": "payload.success",
788
+ "statusType": "auto",
789
+ "x": 850,
790
+ "y": 1360
791
+ },
792
+ {
793
+ "id": "comment-edge",
794
+ "type": "comment",
795
+ "z": "questdb-examples-tab",
796
+ "name": "--- Edge Cases ---",
797
+ "info": "",
798
+ "x": 140,
799
+ "y": 1440
800
+ },
801
+ {
802
+ "id": "inject-edge-null",
803
+ "type": "inject",
804
+ "z": "questdb-examples-tab",
805
+ "name": "Null/undefined handling",
806
+ "props": [
807
+ {"p": "payload"},
808
+ {"p": "topic", "vt": "str"}
809
+ ],
810
+ "repeat": "",
811
+ "crontab": "",
812
+ "once": false,
813
+ "onceDelay": 0.1,
814
+ "topic": "edge_cases",
815
+ "payload": "{}",
816
+ "payloadType": "json",
817
+ "x": 180,
818
+ "y": 1500,
819
+ "wires": [["function-edge-null"]]
820
+ },
821
+ {
822
+ "id": "function-edge-null",
823
+ "type": "function",
824
+ "z": "questdb-examples-tab",
825
+ "name": "Test null handling",
826
+ "func": "msg.payload = {\n symbols: {\n test_type: \"null_values\",\n nullable_symbol: null, // Skipped\n valid_symbol: \"present\"\n },\n columns: {\n valid_value: 42,\n null_value: null, // Skipped\n undefined_value: undefined, // Skipped\n zero_value: 0, // Included\n empty_string: \"\", // Included\n false_boolean: false, // Included\n empty_array: [] // Included\n },\n timestamp: Date.now()\n};\nreturn msg;",
827
+ "outputs": 1,
828
+ "x": 410,
829
+ "y": 1500,
830
+ "wires": [["questdb-write-edge", "debug-edge"]]
831
+ },
832
+ {
833
+ "id": "inject-edge-special",
834
+ "type": "inject",
835
+ "z": "questdb-examples-tab",
836
+ "name": "Special numeric values",
837
+ "props": [
838
+ {"p": "payload"},
839
+ {"p": "topic", "vt": "str"}
840
+ ],
841
+ "repeat": "",
842
+ "crontab": "",
843
+ "once": false,
844
+ "onceDelay": 0.1,
845
+ "topic": "edge_cases",
846
+ "payload": "{}",
847
+ "payloadType": "json",
848
+ "x": 180,
849
+ "y": 1560,
850
+ "wires": [["function-edge-special"]]
851
+ },
852
+ {
853
+ "id": "function-edge-special",
854
+ "type": "function",
855
+ "z": "questdb-examples-tab",
856
+ "name": "Test special numbers",
857
+ "func": "msg.payload = {\n symbols: {\n test_type: \"special_numbers\"\n },\n columns: {\n zero: 0,\n negative_zero: -0,\n very_small: 0.000000001,\n very_large: 999999999999.999,\n max_safe_int: { value: Number.MAX_SAFE_INTEGER, type: 'long' },\n precise_decimal: { value: '123456789.123456789', type: 'decimal' }\n // Note: Infinity and NaN are skipped\n },\n timestamp: Date.now()\n};\nreturn msg;",
858
+ "outputs": 1,
859
+ "x": 420,
860
+ "y": 1560,
861
+ "wires": [["questdb-write-edge", "debug-edge"]]
862
+ },
863
+ {
864
+ "id": "questdb-write-edge",
865
+ "type": "questdb",
866
+ "z": "questdb-examples-tab",
867
+ "name": "Write edge cases",
868
+ "questdb": "questdb-config-examples",
869
+ "autoFlush": true,
870
+ "flushInterval": 1000,
871
+ "x": 680,
872
+ "y": 1530,
873
+ "wires": [["debug-edge-result"]]
874
+ },
875
+ {
876
+ "id": "debug-edge",
877
+ "type": "debug",
878
+ "z": "questdb-examples-tab",
879
+ "name": "Payload",
880
+ "active": true,
881
+ "tosidebar": true,
882
+ "console": false,
883
+ "tostatus": false,
884
+ "complete": "payload",
885
+ "targetType": "msg",
886
+ "x": 680,
887
+ "y": 1480
888
+ },
889
+ {
890
+ "id": "debug-edge-result",
891
+ "type": "debug",
892
+ "z": "questdb-examples-tab",
893
+ "name": "Result",
894
+ "active": true,
895
+ "tosidebar": true,
896
+ "console": false,
897
+ "tostatus": true,
898
+ "complete": "payload",
899
+ "targetType": "msg",
900
+ "statusVal": "payload.success",
901
+ "statusType": "auto",
902
+ "x": 870,
903
+ "y": 1530
904
+ },
905
+ {
906
+ "id": "questdb-config-examples",
907
+ "type": "questdb-config",
908
+ "name": "Local QuestDB",
909
+ "protocol": "http",
910
+ "host": "localhost",
911
+ "port": "9000",
912
+ "tlsVerify": true,
913
+ "tlsCa": "",
914
+ "autoFlush": true,
915
+ "autoFlushRows": "75000",
916
+ "autoFlushInterval": "1000",
917
+ "requestTimeout": "10000",
918
+ "retryTimeout": "10000",
919
+ "initBufSize": "65536",
920
+ "maxBufSize": "104857600",
921
+ "useAuth": false,
922
+ "authType": "basic"
923
+ }
924
+ ]