node-red-contrib-i3x 0.0.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.
@@ -0,0 +1,1272 @@
1
+ [
2
+ {
3
+ "id": "i3x-demo-tab",
4
+ "type": "tab",
5
+ "label": "i3X Complete Demo",
6
+ "disabled": false,
7
+ "info": "Complete demo of all i3X nodes against the public CESMII demo server.\n\n**Server:** https://i3x.cesmii.net\n**Auth:** None (public)\n\nThis flow demonstrates all 5 operation nodes:\n1. **Browse** – Explore the information model\n2. **Read** – Read current values\n3. **Write** – Write values\n4. **History** – Query historical data\n5. **Subscribe** – Monitor value changes"
8
+ },
9
+ {
10
+ "id": "i3x-demo-server",
11
+ "type": "i3x-server",
12
+ "name": "CESMII Demo",
13
+ "baseUrl": "https://i3x.cesmii.net",
14
+ "apiVersion": "",
15
+ "authType": "none",
16
+ "timeout": "10000",
17
+ "tlsConfig": ""
18
+ },
19
+ {
20
+ "id": "comment-section-browse",
21
+ "type": "comment",
22
+ "z": "i3x-demo-tab",
23
+ "name": "=== 1. BROWSE - Explore the information model ===",
24
+ "info": "The **i3x-browse** node explores the i3X information model.\n\nThe i3X API is graph-based: objects have types, belong to namespaces, and are connected through relationships.\n\n**Browse targets:**\n- `namespaces` – All available namespaces\n- `objecttypes` – Type definitions (schemas)\n- `relationshiptypes` – Relationship type definitions (e.g. HasChildren)\n- `objects` – Object instances\n- `related` – Graph traversal (related objects)\n\nClick the inject nodes on the left to execute the queries.",
25
+ "x": 310,
26
+ "y": 40,
27
+ "wires": []
28
+ },
29
+ {
30
+ "id": "inject-ns",
31
+ "type": "inject",
32
+ "z": "i3x-demo-tab",
33
+ "name": ">> Get Namespaces",
34
+ "props": [],
35
+ "repeat": "",
36
+ "crontab": "",
37
+ "once": false,
38
+ "onceDelay": 0.1,
39
+ "topic": "",
40
+ "x": 150,
41
+ "y": 100,
42
+ "wires": [
43
+ [
44
+ "browse-ns"
45
+ ]
46
+ ]
47
+ },
48
+ {
49
+ "id": "browse-ns",
50
+ "type": "i3x-browse",
51
+ "z": "i3x-demo-tab",
52
+ "name": "Namespaces",
53
+ "server": "i3x-demo-server",
54
+ "browseTarget": "namespaces",
55
+ "elementId": "",
56
+ "typeId": "",
57
+ "namespaceUri": "",
58
+ "includeMetadata": false,
59
+ "relationshipType": "",
60
+ "x": 380,
61
+ "y": 100,
62
+ "wires": [
63
+ [
64
+ "debug-ns"
65
+ ]
66
+ ]
67
+ },
68
+ {
69
+ "id": "debug-ns",
70
+ "type": "debug",
71
+ "z": "i3x-demo-tab",
72
+ "name": "Namespaces",
73
+ "active": true,
74
+ "tosidebar": true,
75
+ "console": false,
76
+ "tostatus": true,
77
+ "complete": "payload",
78
+ "targetType": "msg",
79
+ "statusVal": "payload.length",
80
+ "statusType": "msg",
81
+ "x": 580,
82
+ "y": 100,
83
+ "wires": []
84
+ },
85
+ {
86
+ "id": "inject-types",
87
+ "type": "inject",
88
+ "z": "i3x-demo-tab",
89
+ "name": ">> Get Object Types",
90
+ "props": [],
91
+ "repeat": "",
92
+ "crontab": "",
93
+ "once": false,
94
+ "onceDelay": 0.1,
95
+ "topic": "",
96
+ "x": 160,
97
+ "y": 160,
98
+ "wires": [
99
+ [
100
+ "browse-types"
101
+ ]
102
+ ]
103
+ },
104
+ {
105
+ "id": "browse-types",
106
+ "type": "i3x-browse",
107
+ "z": "i3x-demo-tab",
108
+ "name": "Object Types",
109
+ "server": "i3x-demo-server",
110
+ "browseTarget": "objecttypes",
111
+ "elementId": "",
112
+ "typeId": "",
113
+ "namespaceUri": "",
114
+ "includeMetadata": false,
115
+ "relationshipType": "",
116
+ "x": 390,
117
+ "y": 160,
118
+ "wires": [
119
+ [
120
+ "debug-types"
121
+ ]
122
+ ]
123
+ },
124
+ {
125
+ "id": "debug-types",
126
+ "type": "debug",
127
+ "z": "i3x-demo-tab",
128
+ "name": "Object Types",
129
+ "active": true,
130
+ "tosidebar": true,
131
+ "console": false,
132
+ "tostatus": false,
133
+ "complete": "payload",
134
+ "targetType": "msg",
135
+ "x": 590,
136
+ "y": 160,
137
+ "wires": []
138
+ },
139
+ {
140
+ "id": "inject-reltypes",
141
+ "type": "inject",
142
+ "z": "i3x-demo-tab",
143
+ "name": ">> Relationship Types",
144
+ "props": [],
145
+ "repeat": "",
146
+ "crontab": "",
147
+ "once": false,
148
+ "onceDelay": 0.1,
149
+ "topic": "",
150
+ "x": 160,
151
+ "y": 220,
152
+ "wires": [
153
+ [
154
+ "browse-reltypes"
155
+ ]
156
+ ]
157
+ },
158
+ {
159
+ "id": "browse-reltypes",
160
+ "type": "i3x-browse",
161
+ "z": "i3x-demo-tab",
162
+ "name": "Relationship Types",
163
+ "server": "i3x-demo-server",
164
+ "browseTarget": "relationshiptypes",
165
+ "elementId": "",
166
+ "typeId": "",
167
+ "namespaceUri": "",
168
+ "includeMetadata": false,
169
+ "relationshipType": "",
170
+ "x": 410,
171
+ "y": 220,
172
+ "wires": [
173
+ [
174
+ "debug-reltypes"
175
+ ]
176
+ ]
177
+ },
178
+ {
179
+ "id": "debug-reltypes",
180
+ "type": "debug",
181
+ "z": "i3x-demo-tab",
182
+ "name": "Rel. Types",
183
+ "active": true,
184
+ "tosidebar": true,
185
+ "console": false,
186
+ "tostatus": false,
187
+ "complete": "payload",
188
+ "targetType": "msg",
189
+ "x": 610,
190
+ "y": 220,
191
+ "wires": []
192
+ },
193
+ {
194
+ "id": "inject-objects",
195
+ "type": "inject",
196
+ "z": "i3x-demo-tab",
197
+ "name": ">> List All Objects",
198
+ "props": [],
199
+ "repeat": "",
200
+ "crontab": "",
201
+ "once": false,
202
+ "onceDelay": 0.1,
203
+ "topic": "",
204
+ "x": 150,
205
+ "y": 280,
206
+ "wires": [
207
+ [
208
+ "browse-objects"
209
+ ]
210
+ ]
211
+ },
212
+ {
213
+ "id": "browse-objects",
214
+ "type": "i3x-browse",
215
+ "z": "i3x-demo-tab",
216
+ "name": "All Objects",
217
+ "server": "i3x-demo-server",
218
+ "browseTarget": "objects",
219
+ "elementId": "",
220
+ "typeId": "",
221
+ "namespaceUri": "",
222
+ "includeMetadata": true,
223
+ "relationshipType": "",
224
+ "x": 380,
225
+ "y": 280,
226
+ "wires": [
227
+ [
228
+ "debug-objects"
229
+ ]
230
+ ]
231
+ },
232
+ {
233
+ "id": "debug-objects",
234
+ "type": "debug",
235
+ "z": "i3x-demo-tab",
236
+ "name": "Objects",
237
+ "active": true,
238
+ "tosidebar": true,
239
+ "console": false,
240
+ "tostatus": false,
241
+ "complete": "payload",
242
+ "targetType": "msg",
243
+ "x": 580,
244
+ "y": 280,
245
+ "wires": []
246
+ },
247
+ {
248
+ "id": "inject-objects-filter",
249
+ "type": "inject",
250
+ "z": "i3x-demo-tab",
251
+ "name": ">> Filter Objects by Type",
252
+ "props": [
253
+ {
254
+ "p": "typeId",
255
+ "v": "work-unit-type",
256
+ "vt": "str"
257
+ }
258
+ ],
259
+ "repeat": "",
260
+ "crontab": "",
261
+ "once": false,
262
+ "onceDelay": 0.1,
263
+ "topic": "",
264
+ "x": 170,
265
+ "y": 340,
266
+ "wires": [
267
+ [
268
+ "browse-objects-filter"
269
+ ]
270
+ ]
271
+ },
272
+ {
273
+ "id": "browse-objects-filter",
274
+ "type": "i3x-browse",
275
+ "z": "i3x-demo-tab",
276
+ "name": "Objects (work-unit-type)",
277
+ "server": "i3x-demo-server",
278
+ "browseTarget": "objects",
279
+ "elementId": "",
280
+ "typeId": "work-unit-type",
281
+ "namespaceUri": "",
282
+ "includeMetadata": false,
283
+ "relationshipType": "",
284
+ "x": 430,
285
+ "y": 340,
286
+ "wires": [
287
+ [
288
+ "debug-objects-filter"
289
+ ]
290
+ ]
291
+ },
292
+ {
293
+ "id": "debug-objects-filter",
294
+ "type": "debug",
295
+ "z": "i3x-demo-tab",
296
+ "name": "Filtered Objects",
297
+ "active": true,
298
+ "tosidebar": true,
299
+ "console": false,
300
+ "tostatus": false,
301
+ "complete": "payload",
302
+ "targetType": "msg",
303
+ "x": 660,
304
+ "y": 340,
305
+ "wires": []
306
+ },
307
+ {
308
+ "id": "inject-related",
309
+ "type": "inject",
310
+ "z": "i3x-demo-tab",
311
+ "name": ">> Related Objects (pump-station)",
312
+ "props": [
313
+ {
314
+ "p": "elementId",
315
+ "v": "pump-station",
316
+ "vt": "str"
317
+ }
318
+ ],
319
+ "repeat": "",
320
+ "crontab": "",
321
+ "once": false,
322
+ "onceDelay": 0.1,
323
+ "topic": "",
324
+ "x": 200,
325
+ "y": 400,
326
+ "wires": [
327
+ [
328
+ "browse-related"
329
+ ]
330
+ ]
331
+ },
332
+ {
333
+ "id": "browse-related",
334
+ "type": "i3x-browse",
335
+ "z": "i3x-demo-tab",
336
+ "name": "Related Objects",
337
+ "server": "i3x-demo-server",
338
+ "browseTarget": "related",
339
+ "elementId": "",
340
+ "typeId": "",
341
+ "namespaceUri": "",
342
+ "includeMetadata": true,
343
+ "relationshipType": "",
344
+ "x": 430,
345
+ "y": 400,
346
+ "wires": [
347
+ [
348
+ "debug-related"
349
+ ]
350
+ ]
351
+ },
352
+ {
353
+ "id": "debug-related",
354
+ "type": "debug",
355
+ "z": "i3x-demo-tab",
356
+ "name": "Related",
357
+ "active": true,
358
+ "tosidebar": true,
359
+ "console": false,
360
+ "tostatus": false,
361
+ "complete": "payload",
362
+ "targetType": "msg",
363
+ "x": 620,
364
+ "y": 400,
365
+ "wires": []
366
+ },
367
+ {
368
+ "id": "inject-by-id",
369
+ "type": "inject",
370
+ "z": "i3x-demo-tab",
371
+ "name": ">> Load Object by ID",
372
+ "props": [
373
+ {
374
+ "p": "elementId",
375
+ "v": "pump-101",
376
+ "vt": "str"
377
+ }
378
+ ],
379
+ "repeat": "",
380
+ "crontab": "",
381
+ "once": false,
382
+ "onceDelay": 0.1,
383
+ "topic": "",
384
+ "x": 160,
385
+ "y": 460,
386
+ "wires": [
387
+ [
388
+ "browse-by-id"
389
+ ]
390
+ ]
391
+ },
392
+ {
393
+ "id": "browse-by-id",
394
+ "type": "i3x-browse",
395
+ "z": "i3x-demo-tab",
396
+ "name": "Object by ID",
397
+ "server": "i3x-demo-server",
398
+ "browseTarget": "objects",
399
+ "elementId": "",
400
+ "typeId": "",
401
+ "namespaceUri": "",
402
+ "includeMetadata": true,
403
+ "relationshipType": "",
404
+ "x": 390,
405
+ "y": 460,
406
+ "wires": [
407
+ [
408
+ "debug-by-id"
409
+ ]
410
+ ]
411
+ },
412
+ {
413
+ "id": "debug-by-id",
414
+ "type": "debug",
415
+ "z": "i3x-demo-tab",
416
+ "name": "Object Detail",
417
+ "active": true,
418
+ "tosidebar": true,
419
+ "console": false,
420
+ "tostatus": false,
421
+ "complete": "payload",
422
+ "targetType": "msg",
423
+ "x": 590,
424
+ "y": 460,
425
+ "wires": []
426
+ },
427
+ {
428
+ "id": "comment-section-read",
429
+ "type": "comment",
430
+ "z": "i3x-demo-tab",
431
+ "name": "=== 2. READ - Read current values ===",
432
+ "info": "The **i3x-read** node reads the last known values of one or more objects.\n\n**API endpoint:** `POST /objects/value`\n\n**Key parameters:**\n- `elementIds` – Which objects to read (comma-separated or array)\n- `maxDepth` – Recursion depth:\n - `1` = this element only (default)\n - `0` = infinite depth (include all child components)\n\n**Analogy:** Comparable to OPC UA Read or S7 IN.",
433
+ "x": 280,
434
+ "y": 540,
435
+ "wires": []
436
+ },
437
+ {
438
+ "id": "inject-read-single",
439
+ "type": "inject",
440
+ "z": "i3x-demo-tab",
441
+ "name": ">> Read Single Value (pump-101-state)",
442
+ "props": [],
443
+ "repeat": "",
444
+ "crontab": "",
445
+ "once": false,
446
+ "onceDelay": 0.1,
447
+ "topic": "",
448
+ "x": 220,
449
+ "y": 600,
450
+ "wires": [
451
+ [
452
+ "read-single"
453
+ ]
454
+ ]
455
+ },
456
+ {
457
+ "id": "read-single",
458
+ "type": "i3x-read",
459
+ "z": "i3x-demo-tab",
460
+ "name": "Pump State",
461
+ "server": "i3x-demo-server",
462
+ "elementIds": "pump-101-state",
463
+ "maxDepth": "1",
464
+ "x": 460,
465
+ "y": 600,
466
+ "wires": [
467
+ [
468
+ "debug-read-single"
469
+ ]
470
+ ]
471
+ },
472
+ {
473
+ "id": "debug-read-single",
474
+ "type": "debug",
475
+ "z": "i3x-demo-tab",
476
+ "name": "Pump State Value",
477
+ "active": true,
478
+ "tosidebar": true,
479
+ "console": false,
480
+ "tostatus": false,
481
+ "complete": "payload",
482
+ "targetType": "msg",
483
+ "x": 660,
484
+ "y": 600,
485
+ "wires": []
486
+ },
487
+ {
488
+ "id": "inject-read-multi",
489
+ "type": "inject",
490
+ "z": "i3x-demo-tab",
491
+ "name": ">> Read Multiple Values",
492
+ "props": [
493
+ {
494
+ "p": "elementIds",
495
+ "v": "[\"pump-101-state\",\"pump-101-bearing-temperature\"]",
496
+ "vt": "json"
497
+ }
498
+ ],
499
+ "repeat": "",
500
+ "crontab": "",
501
+ "once": false,
502
+ "onceDelay": 0.1,
503
+ "topic": "",
504
+ "x": 170,
505
+ "y": 660,
506
+ "wires": [
507
+ [
508
+ "read-multi"
509
+ ]
510
+ ]
511
+ },
512
+ {
513
+ "id": "read-multi",
514
+ "type": "i3x-read",
515
+ "z": "i3x-demo-tab",
516
+ "name": "State + Temperature",
517
+ "server": "i3x-demo-server",
518
+ "elementIds": "",
519
+ "maxDepth": "1",
520
+ "x": 460,
521
+ "y": 660,
522
+ "wires": [
523
+ [
524
+ "debug-read-multi"
525
+ ]
526
+ ]
527
+ },
528
+ {
529
+ "id": "debug-read-multi",
530
+ "type": "debug",
531
+ "z": "i3x-demo-tab",
532
+ "name": "Multiple Values",
533
+ "active": true,
534
+ "tosidebar": true,
535
+ "console": false,
536
+ "tostatus": false,
537
+ "complete": "payload",
538
+ "targetType": "msg",
539
+ "x": 660,
540
+ "y": 660,
541
+ "wires": []
542
+ },
543
+ {
544
+ "id": "inject-read-deep",
545
+ "type": "inject",
546
+ "z": "i3x-demo-tab",
547
+ "name": ">> Recursive Read (pump-101, depth=0)",
548
+ "props": [
549
+ {
550
+ "p": "maxDepth",
551
+ "v": "0",
552
+ "vt": "num"
553
+ }
554
+ ],
555
+ "repeat": "",
556
+ "crontab": "",
557
+ "once": false,
558
+ "onceDelay": 0.1,
559
+ "topic": "",
560
+ "x": 210,
561
+ "y": 720,
562
+ "wires": [
563
+ [
564
+ "read-deep"
565
+ ]
566
+ ]
567
+ },
568
+ {
569
+ "id": "read-deep",
570
+ "type": "i3x-read",
571
+ "z": "i3x-demo-tab",
572
+ "name": "Pump-101 (recursive)",
573
+ "server": "i3x-demo-server",
574
+ "elementIds": "pump-101",
575
+ "maxDepth": "1",
576
+ "x": 470,
577
+ "y": 720,
578
+ "wires": [
579
+ [
580
+ "debug-read-deep"
581
+ ]
582
+ ]
583
+ },
584
+ {
585
+ "id": "debug-read-deep",
586
+ "type": "debug",
587
+ "z": "i3x-demo-tab",
588
+ "name": "All Nested Values",
589
+ "active": true,
590
+ "tosidebar": true,
591
+ "console": false,
592
+ "tostatus": false,
593
+ "complete": "payload",
594
+ "targetType": "msg",
595
+ "x": 670,
596
+ "y": 720,
597
+ "wires": []
598
+ },
599
+ {
600
+ "id": "comment-section-write",
601
+ "type": "comment",
602
+ "z": "i3x-demo-tab",
603
+ "name": "=== 3. WRITE - Write values ===",
604
+ "info": "The **i3x-write** node writes a value to an i3X object.\n\n**API endpoint:** `PUT /objects/{elementId}/value`\n\n**Input:**\n- `msg.payload` - The value to write (must match the element's type schema)\n- `msg.elementId` or node property - Target element\n\n**Output:**\n- `msg.payload` - Server confirmation (`{ success, message }`)\n- `msg.elementId` - The element ID that was written to\n\n**Payload format depends on the element type:**\n- `state-type` → object: `{ description, color, type: { id, name, description }, metadata: { ... } }`\n- `measurement-value-type` / `sensor-type` → plain number (e.g. `72.5`)\n- `measurement-health-type` → integer (e.g. `95`)\n\n**Analogy:** Comparable to OPC UA Write or S7 OUT.",
605
+ "x": 270,
606
+ "y": 800,
607
+ "wires": []
608
+ },
609
+ {
610
+ "id": "inject-write",
611
+ "type": "inject",
612
+ "z": "i3x-demo-tab",
613
+ "name": ">> Write State (object)",
614
+ "props": [
615
+ {
616
+ "p": "payload",
617
+ "v": "{\"description\":\"Pump is running\",\"color\":\"#00FF00\",\"type\":{\"id\":1,\"name\":\"Running\",\"description\":\"Equipment running normally\"},\"metadata\":{\"source\":\"node-red\",\"uri\":\"demo-flow\",\"asset\":{\"id\":0,\"name\":\"Pump-101\",\"description\":\"Centrifugal water pump\"}}}",
618
+ "vt": "json"
619
+ },
620
+ {
621
+ "p": "elementId",
622
+ "v": "pump-101-state",
623
+ "vt": "str"
624
+ }
625
+ ],
626
+ "repeat": "",
627
+ "crontab": "",
628
+ "once": false,
629
+ "onceDelay": 0.1,
630
+ "topic": "",
631
+ "x": 140,
632
+ "y": 860,
633
+ "wires": [
634
+ [
635
+ "write-node"
636
+ ]
637
+ ]
638
+ },
639
+ {
640
+ "id": "write-node",
641
+ "type": "i3x-write",
642
+ "z": "i3x-demo-tab",
643
+ "name": "Write pump-101-state",
644
+ "server": "i3x-demo-server",
645
+ "elementId": "",
646
+ "x": 430,
647
+ "y": 860,
648
+ "wires": [
649
+ [
650
+ "debug-write"
651
+ ]
652
+ ]
653
+ },
654
+ {
655
+ "id": "debug-write",
656
+ "type": "debug",
657
+ "z": "i3x-demo-tab",
658
+ "name": "Write Result",
659
+ "active": true,
660
+ "tosidebar": true,
661
+ "console": false,
662
+ "tostatus": false,
663
+ "complete": "true",
664
+ "targetType": "full",
665
+ "x": 650,
666
+ "y": 860,
667
+ "wires": []
668
+ },
669
+ {
670
+ "id": "inject-write-dynamic",
671
+ "type": "inject",
672
+ "z": "i3x-demo-tab",
673
+ "name": ">> Dynamic Write (numeric value via msg)",
674
+ "props": [
675
+ {
676
+ "p": "payload",
677
+ "v": "72.5",
678
+ "vt": "num"
679
+ },
680
+ {
681
+ "p": "elementId",
682
+ "v": "pump-101-measurements-bearing-temperature-value",
683
+ "vt": "str"
684
+ }
685
+ ],
686
+ "repeat": "",
687
+ "crontab": "",
688
+ "once": false,
689
+ "onceDelay": 0.1,
690
+ "topic": "",
691
+ "x": 210,
692
+ "y": 920,
693
+ "wires": [
694
+ [
695
+ "write-dynamic"
696
+ ]
697
+ ]
698
+ },
699
+ {
700
+ "id": "write-dynamic",
701
+ "type": "i3x-write",
702
+ "z": "i3x-demo-tab",
703
+ "name": "Write (dynamic)",
704
+ "server": "i3x-demo-server",
705
+ "elementId": "",
706
+ "x": 430,
707
+ "y": 920,
708
+ "wires": [
709
+ [
710
+ "debug-write-dynamic"
711
+ ]
712
+ ]
713
+ },
714
+ {
715
+ "id": "debug-write-dynamic",
716
+ "type": "debug",
717
+ "z": "i3x-demo-tab",
718
+ "name": "Write Dyn. Result",
719
+ "active": true,
720
+ "tosidebar": true,
721
+ "console": false,
722
+ "tostatus": false,
723
+ "complete": "true",
724
+ "targetType": "full",
725
+ "x": 660,
726
+ "y": 920,
727
+ "wires": []
728
+ },
729
+ {
730
+ "id": "inject-write-history",
731
+ "type": "inject",
732
+ "z": "i3x-demo-tab",
733
+ "name": ">> Write History",
734
+ "props": [
735
+ {
736
+ "p": "payload",
737
+ "v": "[{\"value\":68.2,\"quality\":\"GOOD\",\"timestamp\":\"2025-06-01T10:00:00Z\"},{\"value\":69.1,\"quality\":\"GOOD\",\"timestamp\":\"2025-06-01T10:05:00Z\"},{\"value\":70.5,\"quality\":\"GOOD\",\"timestamp\":\"2025-06-01T10:10:00Z\"}]",
738
+ "vt": "json"
739
+ },
740
+ {
741
+ "p": "elementId",
742
+ "v": "pump-101-measurements-bearing-temperature-value",
743
+ "vt": "str"
744
+ }
745
+ ],
746
+ "repeat": "",
747
+ "crontab": "",
748
+ "once": false,
749
+ "onceDelay": 0.1,
750
+ "topic": "",
751
+ "x": 150,
752
+ "y": 980,
753
+ "wires": [
754
+ [
755
+ "write-history-node"
756
+ ]
757
+ ]
758
+ },
759
+ {
760
+ "id": "write-history-node",
761
+ "type": "i3x-write",
762
+ "z": "i3x-demo-tab",
763
+ "name": "Write History",
764
+ "server": "i3x-demo-server",
765
+ "writeTarget": "history",
766
+ "elementId": "",
767
+ "x": 430,
768
+ "y": 980,
769
+ "wires": [
770
+ [
771
+ "debug-write-history"
772
+ ]
773
+ ]
774
+ },
775
+ {
776
+ "id": "debug-write-history",
777
+ "type": "debug",
778
+ "z": "i3x-demo-tab",
779
+ "name": "Write History Result",
780
+ "active": true,
781
+ "tosidebar": true,
782
+ "console": false,
783
+ "tostatus": false,
784
+ "complete": "true",
785
+ "targetType": "full",
786
+ "x": 670,
787
+ "y": 980,
788
+ "wires": []
789
+ },
790
+ {
791
+ "id": "comment-section-history",
792
+ "type": "comment",
793
+ "z": "i3x-demo-tab",
794
+ "name": "=== 4. HISTORY - Query historical data ===",
795
+ "info": "The **i3x-history** node queries historical time-series data.\n\n**API endpoint:** `POST /objects/history`\n\n**Time formats:**\n- ISO 8601: `2025-01-01T00:00:00Z`\n- Relative: `-30s`, `-5m`, `-1h`, `-7d`, `-1w`\n\n**Parameters:**\n- `elementIds` – Which objects to query\n- `startTime` – Start of time range\n- `endTime` – End of time range (default: now)\n- `maxDepth` – Recursion into child objects\n\n**Analogy:** Comparable to a historian query node.",
796
+ "x": 300,
797
+ "y": 1060,
798
+ "wires": []
799
+ },
800
+ {
801
+ "id": "inject-history-1h",
802
+ "type": "inject",
803
+ "z": "i3x-demo-tab",
804
+ "name": ">> Last Hour",
805
+ "props": [],
806
+ "repeat": "",
807
+ "crontab": "",
808
+ "once": false,
809
+ "onceDelay": 0.1,
810
+ "topic": "",
811
+ "x": 130,
812
+ "y": 1120,
813
+ "wires": [
814
+ [
815
+ "history-1h"
816
+ ]
817
+ ]
818
+ },
819
+ {
820
+ "id": "history-1h",
821
+ "type": "i3x-history",
822
+ "z": "i3x-demo-tab",
823
+ "name": "pump-101 (last 1h)",
824
+ "server": "i3x-demo-server",
825
+ "elementIds": "pump-101-bearing-temperature",
826
+ "startTime": "-1h",
827
+ "endTime": "",
828
+ "maxDepth": "1",
829
+ "x": 430,
830
+ "y": 1120,
831
+ "wires": [
832
+ [
833
+ "debug-history-1h"
834
+ ]
835
+ ]
836
+ },
837
+ {
838
+ "id": "debug-history-1h",
839
+ "type": "debug",
840
+ "z": "i3x-demo-tab",
841
+ "name": "History 1h",
842
+ "active": true,
843
+ "tosidebar": true,
844
+ "console": false,
845
+ "tostatus": false,
846
+ "complete": "payload",
847
+ "targetType": "msg",
848
+ "x": 650,
849
+ "y": 1120,
850
+ "wires": []
851
+ },
852
+ {
853
+ "id": "inject-history-7d",
854
+ "type": "inject",
855
+ "z": "i3x-demo-tab",
856
+ "name": ">> Last 7 Days",
857
+ "props": [],
858
+ "repeat": "",
859
+ "crontab": "",
860
+ "once": false,
861
+ "onceDelay": 0.1,
862
+ "topic": "",
863
+ "x": 140,
864
+ "y": 1180,
865
+ "wires": [
866
+ [
867
+ "history-7d"
868
+ ]
869
+ ]
870
+ },
871
+ {
872
+ "id": "history-7d",
873
+ "type": "i3x-history",
874
+ "z": "i3x-demo-tab",
875
+ "name": "pump-101 (last 7d)",
876
+ "server": "i3x-demo-server",
877
+ "elementIds": "pump-101",
878
+ "startTime": "-7d",
879
+ "endTime": "",
880
+ "maxDepth": "0",
881
+ "x": 430,
882
+ "y": 1180,
883
+ "wires": [
884
+ [
885
+ "debug-history-7d"
886
+ ]
887
+ ]
888
+ },
889
+ {
890
+ "id": "debug-history-7d",
891
+ "type": "debug",
892
+ "z": "i3x-demo-tab",
893
+ "name": "History 7d (deep)",
894
+ "active": true,
895
+ "tosidebar": true,
896
+ "console": false,
897
+ "tostatus": false,
898
+ "complete": "payload",
899
+ "targetType": "msg",
900
+ "x": 660,
901
+ "y": 1180,
902
+ "wires": []
903
+ },
904
+ {
905
+ "id": "inject-history-range",
906
+ "type": "inject",
907
+ "z": "i3x-demo-tab",
908
+ "name": ">> Dynamic Time Range via msg",
909
+ "props": [
910
+ {
911
+ "p": "elementIds",
912
+ "v": "[\"pump-101-state\",\"pump-101-bearing-temperature\"]",
913
+ "vt": "json"
914
+ },
915
+ {
916
+ "p": "startTime",
917
+ "v": "-24h",
918
+ "vt": "str"
919
+ },
920
+ {
921
+ "p": "endTime",
922
+ "v": "-1h",
923
+ "vt": "str"
924
+ }
925
+ ],
926
+ "repeat": "",
927
+ "crontab": "",
928
+ "once": false,
929
+ "onceDelay": 0.1,
930
+ "topic": "",
931
+ "x": 190,
932
+ "y": 1240,
933
+ "wires": [
934
+ [
935
+ "history-range"
936
+ ]
937
+ ]
938
+ },
939
+ {
940
+ "id": "history-range",
941
+ "type": "i3x-history",
942
+ "z": "i3x-demo-tab",
943
+ "name": "Multiple IDs (dynamic)",
944
+ "server": "i3x-demo-server",
945
+ "elementIds": "",
946
+ "startTime": "-1h",
947
+ "endTime": "",
948
+ "maxDepth": "1",
949
+ "x": 450,
950
+ "y": 1240,
951
+ "wires": [
952
+ [
953
+ "debug-history-range"
954
+ ]
955
+ ]
956
+ },
957
+ {
958
+ "id": "debug-history-range",
959
+ "type": "debug",
960
+ "z": "i3x-demo-tab",
961
+ "name": "History Range",
962
+ "active": true,
963
+ "tosidebar": true,
964
+ "console": false,
965
+ "tostatus": false,
966
+ "complete": "payload",
967
+ "targetType": "msg",
968
+ "x": 660,
969
+ "y": 1240,
970
+ "wires": []
971
+ },
972
+ {
973
+ "id": "comment-section-subscribe",
974
+ "type": "comment",
975
+ "z": "i3x-demo-tab",
976
+ "name": "=== 5. SUBSCRIBE - Monitor value changes ===",
977
+ "info": "The **i3x-subscribe** node monitors value changes and outputs a message on each update.\n\n**Modes:**\n- **SSE** (Server-Sent Events) – Real-time stream via `GET /subscriptions/{id}/stream`\n- **Polling** – Periodic sync via `POST /subscriptions/{id}/sync`\n\n**Behaviour:**\n- Automatically creates a subscription on deploy\n- Registers the specified element IDs as monitored items\n- Automatically deletes the subscription on stop/re-deploy\n- If SSE fails, automatically falls back to polling\n\n**Analogy:** Comparable to MQTT IN or OPC UA Subscription.\n\n**Note:** This node has no input – it starts automatically on deploy.",
978
+ "x": 310,
979
+ "y": 1320,
980
+ "wires": []
981
+ },
982
+ {
983
+ "id": "subscribe-sse",
984
+ "type": "i3x-subscribe",
985
+ "z": "i3x-demo-tab",
986
+ "name": "SSE Stream (pump-101)",
987
+ "server": "i3x-demo-server",
988
+ "elementIds": "pump-101-state,pump-101-bearing-temperature",
989
+ "mode": "sse",
990
+ "pollingInterval": "5000",
991
+ "maxDepth": "1",
992
+ "x": 170,
993
+ "y": 1400,
994
+ "wires": [
995
+ [
996
+ "debug-subscribe-sse"
997
+ ]
998
+ ]
999
+ },
1000
+ {
1001
+ "id": "debug-subscribe-sse",
1002
+ "type": "debug",
1003
+ "z": "i3x-demo-tab",
1004
+ "name": "SSE Events",
1005
+ "active": true,
1006
+ "tosidebar": true,
1007
+ "console": false,
1008
+ "tostatus": false,
1009
+ "complete": "true",
1010
+ "targetType": "full",
1011
+ "x": 410,
1012
+ "y": 1400,
1013
+ "wires": []
1014
+ },
1015
+ {
1016
+ "id": "subscribe-poll",
1017
+ "type": "i3x-subscribe",
1018
+ "z": "i3x-demo-tab",
1019
+ "name": "Polling (pump-station, 10s)",
1020
+ "server": "i3x-demo-server",
1021
+ "elementIds": "pump-station",
1022
+ "mode": "poll",
1023
+ "pollingInterval": "10000",
1024
+ "maxDepth": "0",
1025
+ "x": 180,
1026
+ "y": 1460,
1027
+ "wires": [
1028
+ [
1029
+ "debug-subscribe-poll"
1030
+ ]
1031
+ ]
1032
+ },
1033
+ {
1034
+ "id": "debug-subscribe-poll",
1035
+ "type": "debug",
1036
+ "z": "i3x-demo-tab",
1037
+ "name": "Poll Updates",
1038
+ "active": true,
1039
+ "tosidebar": true,
1040
+ "console": false,
1041
+ "tostatus": false,
1042
+ "complete": "true",
1043
+ "targetType": "full",
1044
+ "x": 420,
1045
+ "y": 1460,
1046
+ "wires": []
1047
+ },
1048
+ {
1049
+ "id": "comment-section-advanced",
1050
+ "type": "comment",
1051
+ "z": "i3x-demo-tab",
1052
+ "name": "=== 6. EXAMPLE - Browse then Read Pipeline ===",
1053
+ "info": "This example shows a typical chaining pattern:\n\n1. **Browse** all objects\n2. **Function** extracts the element IDs\n3. **Read** fetches the values for all discovered objects\n\nThis pattern is useful when you don't know in advance which objects exist on the server.",
1054
+ "x": 320,
1055
+ "y": 1540,
1056
+ "wires": []
1057
+ },
1058
+ {
1059
+ "id": "inject-pipeline",
1060
+ "type": "inject",
1061
+ "z": "i3x-demo-tab",
1062
+ "name": ">> Browse then Read Pipeline",
1063
+ "props": [],
1064
+ "repeat": "",
1065
+ "crontab": "",
1066
+ "once": false,
1067
+ "onceDelay": 0.1,
1068
+ "topic": "",
1069
+ "x": 180,
1070
+ "y": 1600,
1071
+ "wires": [
1072
+ [
1073
+ "pipeline-browse"
1074
+ ]
1075
+ ]
1076
+ },
1077
+ {
1078
+ "id": "pipeline-browse",
1079
+ "type": "i3x-browse",
1080
+ "z": "i3x-demo-tab",
1081
+ "name": "1. All Objects",
1082
+ "server": "i3x-demo-server",
1083
+ "browseTarget": "objects",
1084
+ "elementId": "",
1085
+ "typeId": "",
1086
+ "namespaceUri": "",
1087
+ "includeMetadata": false,
1088
+ "relationshipType": "",
1089
+ "x": 390,
1090
+ "y": 1600,
1091
+ "wires": [
1092
+ [
1093
+ "pipeline-extract"
1094
+ ]
1095
+ ]
1096
+ },
1097
+ {
1098
+ "id": "pipeline-extract",
1099
+ "type": "function",
1100
+ "z": "i3x-demo-tab",
1101
+ "name": "2. Extract Element IDs",
1102
+ "func": "const ids = msg.payload.map(obj => obj.elementId);\n\nmsg.elementIds = ids;\nmsg.payload = {\n count: ids.length,\n ids: ids\n};\n\nnode.status({text: ids.length + \" objects found\"});\nreturn msg;",
1103
+ "outputs": 1,
1104
+ "timeout": "",
1105
+ "noerr": 0,
1106
+ "initialize": "",
1107
+ "finalize": "",
1108
+ "libs": [],
1109
+ "x": 610,
1110
+ "y": 1600,
1111
+ "wires": [
1112
+ [
1113
+ "pipeline-read",
1114
+ "debug-pipeline-ids"
1115
+ ]
1116
+ ]
1117
+ },
1118
+ {
1119
+ "id": "debug-pipeline-ids",
1120
+ "type": "debug",
1121
+ "z": "i3x-demo-tab",
1122
+ "name": "Discovered IDs",
1123
+ "active": true,
1124
+ "tosidebar": true,
1125
+ "console": false,
1126
+ "tostatus": false,
1127
+ "complete": "payload",
1128
+ "targetType": "msg",
1129
+ "x": 860,
1130
+ "y": 1560,
1131
+ "wires": []
1132
+ },
1133
+ {
1134
+ "id": "pipeline-read",
1135
+ "type": "i3x-read",
1136
+ "z": "i3x-demo-tab",
1137
+ "name": "3. Read All Values",
1138
+ "server": "i3x-demo-server",
1139
+ "elementIds": "",
1140
+ "maxDepth": "0",
1141
+ "x": 860,
1142
+ "y": 1600,
1143
+ "wires": [
1144
+ [
1145
+ "debug-pipeline-values"
1146
+ ]
1147
+ ]
1148
+ },
1149
+ {
1150
+ "id": "debug-pipeline-values",
1151
+ "type": "debug",
1152
+ "z": "i3x-demo-tab",
1153
+ "name": "All Values",
1154
+ "active": true,
1155
+ "tosidebar": true,
1156
+ "console": false,
1157
+ "tostatus": false,
1158
+ "complete": "payload",
1159
+ "targetType": "msg",
1160
+ "x": 1060,
1161
+ "y": 1600,
1162
+ "wires": []
1163
+ },
1164
+ {
1165
+ "id": "comment-section-chain2",
1166
+ "type": "comment",
1167
+ "z": "i3x-demo-tab",
1168
+ "name": "=== 7. EXAMPLE - Related then History Pipeline ===",
1169
+ "info": "Graph traversal combined with historian query:\n\n1. **Browse related** – Find all children of pump-station\n2. **Function** – Extract IDs of composition objects\n3. **History** – Query historical data for the last 24 hours\n\nDemonstrates how to combine graph relationships with time-series queries.",
1170
+ "x": 330,
1171
+ "y": 1680,
1172
+ "wires": []
1173
+ },
1174
+ {
1175
+ "id": "inject-chain2",
1176
+ "type": "inject",
1177
+ "z": "i3x-demo-tab",
1178
+ "name": ">> Related then History Pipeline",
1179
+ "props": [
1180
+ {
1181
+ "p": "elementId",
1182
+ "v": "pump-station",
1183
+ "vt": "str"
1184
+ }
1185
+ ],
1186
+ "repeat": "",
1187
+ "crontab": "",
1188
+ "once": false,
1189
+ "onceDelay": 0.1,
1190
+ "topic": "",
1191
+ "x": 190,
1192
+ "y": 1740,
1193
+ "wires": [
1194
+ [
1195
+ "chain2-browse"
1196
+ ]
1197
+ ]
1198
+ },
1199
+ {
1200
+ "id": "chain2-browse",
1201
+ "type": "i3x-browse",
1202
+ "z": "i3x-demo-tab",
1203
+ "name": "1. Related of pump-station",
1204
+ "server": "i3x-demo-server",
1205
+ "browseTarget": "related",
1206
+ "elementId": "",
1207
+ "typeId": "",
1208
+ "namespaceUri": "",
1209
+ "includeMetadata": false,
1210
+ "relationshipType": "",
1211
+ "x": 440,
1212
+ "y": 1740,
1213
+ "wires": [
1214
+ [
1215
+ "chain2-extract"
1216
+ ]
1217
+ ]
1218
+ },
1219
+ {
1220
+ "id": "chain2-extract",
1221
+ "type": "function",
1222
+ "z": "i3x-demo-tab",
1223
+ "name": "2. Filter Composition IDs",
1224
+ "func": "const compositions = msg.payload.filter(obj => obj.isComposition);\nconst ids = compositions.map(obj => obj.elementId);\n\nmsg.elementIds = ids;\nmsg.startTime = \"-24h\";\n\nnode.status({text: ids.length + \" composition objects\"});\nreturn msg;",
1225
+ "outputs": 1,
1226
+ "timeout": "",
1227
+ "noerr": 0,
1228
+ "initialize": "",
1229
+ "finalize": "",
1230
+ "libs": [],
1231
+ "x": 680,
1232
+ "y": 1740,
1233
+ "wires": [
1234
+ [
1235
+ "chain2-history"
1236
+ ]
1237
+ ]
1238
+ },
1239
+ {
1240
+ "id": "chain2-history",
1241
+ "type": "i3x-history",
1242
+ "z": "i3x-demo-tab",
1243
+ "name": "3. History (24h)",
1244
+ "server": "i3x-demo-server",
1245
+ "elementIds": "",
1246
+ "startTime": "",
1247
+ "endTime": "",
1248
+ "maxDepth": "0",
1249
+ "x": 900,
1250
+ "y": 1740,
1251
+ "wires": [
1252
+ [
1253
+ "debug-chain2"
1254
+ ]
1255
+ ]
1256
+ },
1257
+ {
1258
+ "id": "debug-chain2",
1259
+ "type": "debug",
1260
+ "z": "i3x-demo-tab",
1261
+ "name": "History Result",
1262
+ "active": true,
1263
+ "tosidebar": true,
1264
+ "console": false,
1265
+ "tostatus": false,
1266
+ "complete": "payload",
1267
+ "targetType": "msg",
1268
+ "x": 1100,
1269
+ "y": 1740,
1270
+ "wires": []
1271
+ }
1272
+ ]