@aryacode/dsh-engineering 0.5.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/CHANGELOG.md +52 -0
  2. package/README.md +9 -8
  3. package/cordis.patch.yml +1 -1
  4. package/entries/netlogic.js +266 -0
  5. package/entries/optix.js +13 -0
  6. package/package.json +10 -10
  7. package/vendor/l5x/SKILL.md +27 -7
  8. package/vendor/l5x/lib/engine/change-set.d.ts +9 -1
  9. package/vendor/l5x/lib/engine/change-set.js +32 -7
  10. package/vendor/l5x/lib/engine/documentation.d.ts +58 -0
  11. package/vendor/l5x/lib/engine/documentation.js +237 -0
  12. package/vendor/l5x/lib/engine/instructions.d.ts +50 -0
  13. package/vendor/l5x/lib/engine/instructions.js +107 -0
  14. package/vendor/l5x/lib/engine/ladder.d.ts +74 -0
  15. package/vendor/l5x/lib/engine/ladder.js +209 -0
  16. package/vendor/l5x/lib/index.d.ts +1 -0
  17. package/vendor/l5x/lib/index.js +3 -1
  18. package/vendor/l5x/lib/model/routines.js +6 -1
  19. package/vendor/l5x/lib/session.d.ts +20 -0
  20. package/vendor/l5x/lib/session.js +36 -0
  21. package/vendor/l5x/lib/tools/document.d.ts +18 -0
  22. package/vendor/l5x/lib/tools/document.js +119 -0
  23. package/vendor/l5x/lib/tools/drafts.js +109 -3
  24. package/vendor/optix/SKILL.md +68 -0
  25. package/vendor/optix/netlogic/SOURCE.json +12 -0
  26. package/vendor/optix/netlogic/index.json +1987 -0
  27. package/vendor/optix/netlogic/pages/accessing-project-nodes.md +113 -0
  28. package/vendor/optix/netlogic/pages/advanced-svg.md +124 -0
  29. package/vendor/optix/netlogic/pages/alarming.md +489 -0
  30. package/vendor/optix/netlogic/pages/async-tasks.md +236 -0
  31. package/vendor/optix/netlogic/pages/audit-signature.md +91 -0
  32. package/vendor/optix/netlogic/pages/colors.md +122 -0
  33. package/vendor/optix/netlogic/pages/companion-specs.md +77 -0
  34. package/vendor/optix/netlogic/pages/creating-objects.md +370 -0
  35. package/vendor/optix/netlogic/pages/database-interaction.md +437 -0
  36. package/vendor/optix/netlogic/pages/datagrids.md +123 -0
  37. package/vendor/optix/netlogic/pages/debugging-tips.md +605 -0
  38. package/vendor/optix/netlogic/pages/designtime-tags-import.md +531 -0
  39. package/vendor/optix/netlogic/pages/dialog-boxes.md +150 -0
  40. package/vendor/optix/netlogic/pages/dispatch-events.md +200 -0
  41. package/vendor/optix/netlogic/pages/dynamic-links.md +825 -0
  42. package/vendor/optix/netlogic/pages/element-access.md +1208 -0
  43. package/vendor/optix/netlogic/pages/engineering-units.md +298 -0
  44. package/vendor/optix/netlogic/pages/events.md +340 -0
  45. package/vendor/optix/netlogic/pages/execute-command.md +202 -0
  46. package/vendor/optix/netlogic/pages/fto-studio-cli.md +99 -0
  47. package/vendor/optix/netlogic/pages/good-practices.md +50 -0
  48. package/vendor/optix/netlogic/pages/information-model.md +89 -0
  49. package/vendor/optix/netlogic/pages/log-output.md +22 -0
  50. package/vendor/optix/netlogic/pages/managing-aliases.md +22 -0
  51. package/vendor/optix/netlogic/pages/manipulate-nodes.md +72 -0
  52. package/vendor/optix/netlogic/pages/mqtt.md +240 -0
  53. package/vendor/optix/netlogic/pages/netlogic-lifecycle.md +270 -0
  54. package/vendor/optix/netlogic/pages/netlogic-overview.md +155 -0
  55. package/vendor/optix/netlogic/pages/opcua.md +325 -0
  56. package/vendor/optix/netlogic/pages/plc-tags.md +219 -0
  57. package/vendor/optix/netlogic/pages/queries.md +1297 -0
  58. package/vendor/optix/netlogic/pages/random-generation.md +90 -0
  59. package/vendor/optix/netlogic/pages/recipes.md +375 -0
  60. package/vendor/optix/netlogic/pages/recipex.md +2383 -0
  61. package/vendor/optix/netlogic/pages/regex.md +15 -0
  62. package/vendor/optix/netlogic/pages/register-observers.md +346 -0
  63. package/vendor/optix/netlogic/pages/reports.md +141 -0
  64. package/vendor/optix/netlogic/pages/resource-uri.md +308 -0
  65. package/vendor/optix/netlogic/pages/runtime-tags-import.md +280 -0
  66. package/vendor/optix/netlogic/pages/serial-port.md +357 -0
  67. package/vendor/optix/netlogic/pages/sessions.md +58 -0
  68. package/vendor/optix/netlogic/pages/system-node.md +153 -0
  69. package/vendor/optix/netlogic/pages/template-library.md +127 -0
  70. package/vendor/optix/netlogic/pages/threading.md +236 -0
  71. package/vendor/optix/netlogic/pages/translations.md +417 -0
  72. package/vendor/optix/netlogic/pages/trends.md +128 -0
  73. package/vendor/optix/netlogic/pages/ui-animations.md +115 -0
  74. package/vendor/optix/netlogic/pages/users-groups.md +416 -0
  75. package/vendor/optix/netlogic/pages/variables-formatting.md +16 -0
  76. package/vendor/optix/netlogic/pages/variables-interaction.md +557 -0
  77. package/vendor/optix/netlogic/pages/variables-structure.md +155 -0
@@ -0,0 +1,531 @@
1
+ # Design time import of PLC tags
2
+
3
+ This feature is only supported for TwinCAT and RA Ethernet/IP drivers, and allows you to programmatically import tags from a PLC project file. This can be useful in scenarios where you have to import a determined set of tags from a large PLC project, or when you want to automate the import process as part of your project setup.
4
+
5
+ > [!NOTE]
6
+ > This feature is only available at DesignTime, so it cannot be used in a running application.
7
+
8
+ ## TwinCAT
9
+
10
+ >[!NOTE]
11
+ > This feature is available starting from FactoryTalk Optix 1.7.x
12
+
13
+ To import tags from a TwinCAT PLC, you can use the `TwinCAT` driver. The import process allows you to filter tags based on specific criteria, such as tag name or data type.
14
+
15
+ ```csharp
16
+ #region Using directives
17
+ using System;
18
+ using UAManagedCore;
19
+ using OpcUa = UAManagedCore.OpcUa;
20
+ using FTOptix.UI;
21
+ using FTOptix.HMIProject;
22
+ using FTOptix.NativeUI;
23
+ using FTOptix.Retentivity;
24
+ using FTOptix.CoreBase;
25
+ using FTOptix.Core;
26
+ using FTOptix.NetLogic;
27
+ using FTOptix.TwinCAT;
28
+ using FTOptix.CommunicationDriver;
29
+ using static UAManagedCore.TagImporterAPI;
30
+ using System.Threading.Tasks;
31
+ #endregion
32
+
33
+ public class DesignTimeNetLogic1 : BaseNetLogic
34
+ {
35
+ [ExportMethod]
36
+ public void OfflineImport()
37
+ {
38
+ // First get the existing TwinCAT station from the project
39
+ var station = Project.Current.Get<FTOptix.TwinCAT.Station>("CommDrivers/TwinCATDriver1/TwinCATStation1");
40
+
41
+ // Then get the tag importer node from the station
42
+ var tagImporter = station.TagImporter;
43
+
44
+ // Set the file path to the TwinCAT TPY file you want to import
45
+ tagImporter.FilePath = ResourceUri.FromAbsoluteFilePath("D:\\test\\Optix\\Tools\\TwinCAT\\tpy\\AllSimpleType.tpy");
46
+ tagImporter.Mode = FetchMode.Offline;
47
+
48
+ // Fire and forget, import is run in a background thread
49
+ _ = tagImporter.Import();
50
+ }
51
+
52
+ [ExportMethod]
53
+ public void OfflineImportWithContinuation()
54
+ {
55
+ var station = Project.Current.Get<FTOptix.TwinCAT.Station>("CommDrivers/TwinCATDriver1/TwinCATStation1");
56
+ var tagImporter = station.TagImporter;
57
+
58
+ tagImporter.FilePath = ResourceUri.FromAbsoluteFilePath("D:\\test\\Optix\\Tools\\TwinCAT\\tpy\\AllSimpleType.tpy");
59
+ tagImporter.Mode = FetchMode.Offline;
60
+
61
+ // Import is started in a background thread,
62
+ // continuation is run in the current thread after the import is completed
63
+ var task = tagImporter.Import(Filter);
64
+ task.ContinueWith((t) =>
65
+ {
66
+ if (t.IsFaulted)
67
+ {
68
+ Log.Error("Import task failed: " + t.Exception?.GetBaseException().Message);
69
+ }
70
+ else if (t.IsCanceled)
71
+ {
72
+ Log.Info("Import task was canceled.");
73
+ }
74
+ else
75
+ {
76
+ Log.Info("Import task completed successfully.");
77
+ }
78
+ });
79
+ }
80
+
81
+ [ExportMethod]
82
+ public void OnlineImport()
83
+ {
84
+ var station = Project.Current.Get<FTOptix.TwinCAT.Station>("CommDrivers/TwinCATDriver1/TwinCATStation1");
85
+ var tagImporter = station.TagImporter;
86
+
87
+ tagImporter.Mode = FetchMode.Online;
88
+ _ = tagImporter.Import(Filter);
89
+ }
90
+
91
+
92
+ private bool Filter(string tag, string type)
93
+ {
94
+ // Filter by tag name
95
+ return tag.Contains("int");
96
+
97
+ // or
98
+
99
+ // Filter by type
100
+ // return type == "INT";
101
+ }
102
+ }
103
+ ```
104
+
105
+ An example of TPY file that can be used for testing:
106
+
107
+ ```xml
108
+ <?xml version="1.0" encoding="UTF-8"?>
109
+ <PlcProjectInfo>
110
+ <ProjectInfo>
111
+ <Path>C:\Users\asem\Desktop\TestTwinCAT\TwinCAT Project1\TwinCAT Project1\Untitled1\Untitled1.plcproj</Path>
112
+ <ChangeDate>2018-02-11T04:39:01</ChangeDate>
113
+ <Library>
114
+ <Name>tc2_standard, 3.3.2.0 (beckhoff automation gmbh)</Name>
115
+ </Library>
116
+ <Library>
117
+ <Name>tc2_system, 3.4.17.0 (beckhoff automation gmbh)</Name>
118
+ </Library>
119
+ <Library>
120
+ <Name>tc3_module, 3.3.17.0 (beckhoff automation gmbh)</Name>
121
+ </Library>
122
+ </ProjectInfo>
123
+ <RoutingInfo>
124
+ <AdsInfo>
125
+ <NetId>172.17.17.35.1.1</NetId>
126
+ <Port>851</Port>
127
+ <TargetName>Untitled1</TargetName>
128
+ </AdsInfo>
129
+ </RoutingInfo>
130
+ <CompilerInfo>
131
+ <CpuFamily>Intel X86</CpuFamily>
132
+ <CompilerVersion>3.5.10.20</CompilerVersion>
133
+ <TwinCATVersion>3.4.0.0</TwinCATVersion>
134
+ <TCatPlcCtrlVersion>3.4.0.0</TCatPlcCtrlVersion>
135
+ </CompilerInfo>
136
+ <TargetInfo>
137
+ <CpuFamily>Intel X86</CpuFamily>
138
+ <DataAreaInfo>
139
+ <DataSize>10485760</DataSize>
140
+ <RetainSize>128000</RetainSize>
141
+ <MAreaSize>128000</MAreaSize>
142
+ <InputSize>128000</InputSize>
143
+ <OutputSize>128000</OutputSize>
144
+ </DataAreaInfo>
145
+ </TargetInfo>
146
+ <DataTypes>
147
+ </DataTypes>
148
+ <Symbols>
149
+ <Symbol>
150
+ <Name>MAIN.VarBit</Name>
151
+ <Type>BIT</Type>
152
+ <IGroup>16448</IGroup>
153
+ <IOffset>512508</IOffset>
154
+ <BitSize>8</BitSize>
155
+ </Symbol>
156
+ <Symbol>
157
+ <Name>MAIN.VarDateAndTime</Name>
158
+ <Type>DATE_AND_TIME</Type>
159
+ <IGroup>16448</IGroup>
160
+ <IOffset>512512</IOffset>
161
+ <BitSize>32</BitSize>
162
+ </Symbol>
163
+ <Symbol>
164
+ <Name>MAIN.VarLTime</Name>
165
+ <Type>LTIME</Type>
166
+ <IGroup>16448</IGroup>
167
+ <IOffset>512520</IOffset>
168
+ <BitSize>64</BitSize>
169
+ </Symbol>
170
+ <Symbol>
171
+ <Name>MAIN.VarTime</Name>
172
+ <Type>TIME</Type>
173
+ <IGroup>16448</IGroup>
174
+ <IOffset>512528</IOffset>
175
+ <BitSize>32</BitSize>
176
+ </Symbol>
177
+ <Symbol>
178
+ <Name>MAIN.VarTod</Name>
179
+ <Type>TOD</Type>
180
+ <IGroup>16448</IGroup>
181
+ <IOffset>512532</IOffset>
182
+ <BitSize>32</BitSize>
183
+ </Symbol>
184
+ <Symbol>
185
+ <Name>MAIN.VarDate</Name>
186
+ <Type>DATE</Type>
187
+ <IGroup>16448</IGroup>
188
+ <IOffset>512536</IOffset>
189
+ <BitSize>32</BitSize>
190
+ </Symbol>
191
+ <Symbol>
192
+ <Name>MAIN.VarDT</Name>
193
+ <Type>DT</Type>
194
+ <IGroup>16448</IGroup>
195
+ <IOffset>512540</IOffset>
196
+ <BitSize>32</BitSize>
197
+ </Symbol>
198
+ <Symbol>
199
+ <Name>MAIN.VarBool</Name>
200
+ <Type>BOOL</Type>
201
+ <IGroup>16448</IGroup>
202
+ <IOffset>512594</IOffset>
203
+ <BitSize>8</BitSize>
204
+ </Symbol>
205
+ <Symbol>
206
+ <Name>MAIN.VarByte</Name>
207
+ <Type>BYTE</Type>
208
+ <IGroup>16448</IGroup>
209
+ <IOffset>512595</IOffset>
210
+ <BitSize>8</BitSize>
211
+ </Symbol>
212
+ <Symbol>
213
+ <Name>MAIN.VarDint</Name>
214
+ <Type>DINT</Type>
215
+ <IGroup>16448</IGroup>
216
+ <IOffset>536300</IOffset>
217
+ <BitSize>32</BitSize>
218
+ </Symbol>
219
+ <Symbol>
220
+ <Name>MAIN.VarDword</Name>
221
+ <Type>DWORD</Type>
222
+ <IGroup>16448</IGroup>
223
+ <IOffset>536304</IOffset>
224
+ <BitSize>32</BitSize>
225
+ </Symbol>
226
+ <Symbol>
227
+ <Name>MAIN.VarInt</Name>
228
+ <Type>INT</Type>
229
+ <IGroup>16448</IGroup>
230
+ <IOffset>536308</IOffset>
231
+ <BitSize>16</BitSize>
232
+ </Symbol>
233
+ <Symbol>
234
+ <Name>MAIN.VarSint</Name>
235
+ <Type>SINT</Type>
236
+ <IGroup>16448</IGroup>
237
+ <IOffset>536310</IOffset>
238
+ <BitSize>8</BitSize>
239
+ </Symbol>
240
+ <Symbol>
241
+ <Name>MAIN.VarUsint</Name>
242
+ <Type>USINT</Type>
243
+ <IGroup>16448</IGroup>
244
+ <IOffset>536311</IOffset>
245
+ <BitSize>8</BitSize>
246
+ </Symbol>
247
+ <Symbol>
248
+ <Name>MAIN.VarLint</Name>
249
+ <Type>LINT</Type>
250
+ <IGroup>16448</IGroup>
251
+ <IOffset>536312</IOffset>
252
+ <BitSize>64</BitSize>
253
+ </Symbol>
254
+ <Symbol>
255
+ <Name>MAIN.VarLreal</Name>
256
+ <Type>LREAL</Type>
257
+ <IGroup>16448</IGroup>
258
+ <IOffset>536320</IOffset>
259
+ <BitSize>64</BitSize>
260
+ </Symbol>
261
+ <Symbol>
262
+ <Name>MAIN.VarLWord</Name>
263
+ <Type>LWORD</Type>
264
+ <IGroup>16448</IGroup>
265
+ <IOffset>536328</IOffset>
266
+ <BitSize>64</BitSize>
267
+ </Symbol>
268
+ <Symbol>
269
+ <Name>MAIN.VarReal</Name>
270
+ <Type>REAL</Type>
271
+ <IGroup>16448</IGroup>
272
+ <IOffset>536336</IOffset>
273
+ <BitSize>32</BitSize>
274
+ </Symbol>
275
+ <Symbol>
276
+ <Name>MAIN.VarUint</Name>
277
+ <Type>UINT</Type>
278
+ <IGroup>16448</IGroup>
279
+ <IOffset>536422</IOffset>
280
+ <BitSize>16</BitSize>
281
+ </Symbol>
282
+ <Symbol>
283
+ <Name>MAIN.VarTimOfDay</Name>
284
+ <Type>TIME_OF_DAY</Type>
285
+ <IGroup>16448</IGroup>
286
+ <IOffset>536424</IOffset>
287
+ <BitSize>32</BitSize>
288
+ </Symbol>
289
+ <Symbol>
290
+ <Name>MAIN.VarUdint</Name>
291
+ <Type>UDINT</Type>
292
+ <IGroup>16448</IGroup>
293
+ <IOffset>536428</IOffset>
294
+ <BitSize>32</BitSize>
295
+ </Symbol>
296
+ <Symbol>
297
+ <Name>MAIN.VarUlint</Name>
298
+ <Type>ULINT</Type>
299
+ <IGroup>16448</IGroup>
300
+ <IOffset>536432</IOffset>
301
+ <BitSize>64</BitSize>
302
+ </Symbol>
303
+ <Symbol>
304
+ <Name>MAIN.VarWord</Name>
305
+ <Type>WORD</Type>
306
+ <IGroup>16448</IGroup>
307
+ <IOffset>536440</IOffset>
308
+ <BitSize>16</BitSize>
309
+ </Symbol>
310
+ <Symbol>
311
+ <Name>MAIN.VarWstring</Name>
312
+ <Type>WSTRING(80)</Type>
313
+ <IGroup>16448</IGroup>
314
+ <IOffset>536442</IOffset>
315
+ <BitSize>1296</BitSize>
316
+ </Symbol>
317
+ <Symbol>
318
+ <Name>MAIN.VarString</Name>
319
+ <Type Decoration="40000050">STRING(80)</Type>
320
+ <IGroup>16448</IGroup>
321
+ <IOffset>537880</IOffset>
322
+ <BitSize>648</BitSize>
323
+ </Symbol>
324
+ </Symbols>
325
+ </PlcProjectInfo>
326
+ ```
327
+
328
+ ## RA Ethernet/IP
329
+
330
+ >[!NOTE]
331
+ > This feature is available starting from FactoryTalk Optix 1.8.x
332
+
333
+ To import tags from an Allen-Bradley PLC, you can use the `RA EtherNetIP` driver. The import process allows you to filter tags based on specific criteria, such as tag name or data type.
334
+
335
+ ```csharp
336
+ #region Using directives
337
+ using System;
338
+ using UAManagedCore;
339
+ using OpcUa = UAManagedCore.OpcUa;
340
+ using FTOptix.UI;
341
+ using FTOptix.HMIProject;
342
+ using FTOptix.NativeUI;
343
+ using FTOptix.Retentivity;
344
+ using FTOptix.CoreBase;
345
+ using FTOptix.Core;
346
+ using FTOptix.NetLogic;
347
+ using FTOptix.RAEtherNetIP;
348
+ using FTOptix.CommunicationDriver;
349
+ using static UAManagedCore.TagImporterAPI;
350
+ using System.Threading.Tasks;
351
+ #endregion
352
+
353
+ public class DesignTimeNetLogic1 : BaseNetLogic
354
+ {
355
+ [ExportMethod]
356
+ public void OfflineImport()
357
+ {
358
+ // First get the existing RA EtherNet/IP station from the project
359
+ var station = plcStation;
360
+
361
+ // Then get the tag importer node from the station
362
+ var tagImporter = station.TagImporter;
363
+
364
+ // Set the file path to the L5X file you want to import
365
+ tagImporter.FilePath = filePath;
366
+ tagImporter.Mode = FetchMode.Offline;
367
+
368
+ // Fire and forget, import is run in a background thread
369
+ _ = tagImporter.Import();
370
+ }
371
+
372
+ [ExportMethod]
373
+ public void OfflineImportWithContinuation()
374
+ {
375
+ var station = plcStation;
376
+ var tagImporter = station.TagImporter;
377
+
378
+ tagImporter.FilePath = filePath;
379
+ tagImporter.Mode = FetchMode.Offline;
380
+
381
+ // Import is started in a background thread,
382
+ // continuation is run in the current thread after the import is completed
383
+ var task = tagImporter.Import(Filter);
384
+ task.ContinueWith((t) =>
385
+ {
386
+ if (t.IsFaulted)
387
+ {
388
+ Log.Error("Import task failed: " + t.Exception?.GetBaseException().Message);
389
+ }
390
+ else if (t.IsCanceled)
391
+ {
392
+ Log.Info("Import task was canceled.");
393
+ }
394
+ else
395
+ {
396
+ Log.Info("Import task completed successfully.");
397
+ }
398
+ });
399
+ }
400
+
401
+ [ExportMethod]
402
+ public void OnlineImport()
403
+ {
404
+ var station = plcStation;
405
+ var tagImporter = station.TagImporter;
406
+
407
+ tagImporter.Mode = FetchMode.Online;
408
+ _ = tagImporter.Import(Filter);
409
+ }
410
+
411
+ private bool Filter(string symbolName, string type)
412
+ {
413
+ // List of tags to import (supports partial path matching for parent/child nodes)
414
+ var tagsToImport = new string[]
415
+ {
416
+ "Motor.Status.Running",
417
+ "Integer_tag",
418
+ };
419
+
420
+ foreach (var tagToImport in tagsToImport)
421
+ {
422
+ if (IsTagToImport(symbolName, tagToImport))
423
+ return true;
424
+ }
425
+
426
+ return false;
427
+ }
428
+
429
+ private bool IsTagToImport(string symbolName, string tagToImport)
430
+ {
431
+ // Match if the symbol is an exact match, a parent, or a child of the target tag
432
+ return symbolName == tagToImport ||
433
+ tagToImport.StartsWith(symbolName) ||
434
+ symbolName.StartsWith(tagToImport);
435
+ }
436
+
437
+ private FTOptix.RAEtherNetIP.Station plcStation = Project.Current.Get<FTOptix.RAEtherNetIP.Station>("CommDrivers/RAEtherNetIPDriver1/RAEtherNet_IPStation1");
438
+ private ResourceUri filePath = ResourceUri.FromAbsoluteFilePath("D:\\test\\Optix\\Tools\\RAEtherNetIP\\controller.L5X");
439
+ }
440
+ ```
441
+
442
+ An example of L5X file that can be used for testing:
443
+
444
+ ```xml
445
+ <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
446
+ <RSLogix5000Content SchemaRevision="1.0" SoftwareRevision="38.00" TargetName="test" TargetType="Controller" ContainsContext="false" ExportDate="Wed Mar 11 10:37:10 2026" ExportOptions="NoRawData L5KData DecoratedData ForceProtectedEncoding AllProjDocTrans">
447
+ <Controller Use="Target" Name="test" ProcessorType="1756-L81E" MajorRev="38" MinorRev="11" ProjectCreationDate="Wed Mar 11 10:35:13 2026" LastModifiedDate="Wed Mar 11 10:36:56 2026" SFCExecutionControl="CurrentActive" SFCRestartPosition="MostRecent" SFCLastScan="DontScan" ProjectSN="16#0000_0000"
448
+ MatchProjectToController="false" CanUseRPIFromProducer="false" InhibitAutomaticFirmwareUpdate="0" PassThroughConfiguration="EnabledWithAppend" DownloadProjectDocumentationAndExtendedProperties="true" DownloadProjectCustomProperties="true" ReportMinorOverflow="false" AutoDiagsEnabled="true" WebServerEnabled="false" DataExchangeId="{7815DD91-43A8-4001-B823-F3594DA6D3FC}">
449
+ <RedundancyInfo Enabled="false" KeepTestEditsOnSwitchOver="false"/>
450
+ <Security Code="0" ChangesToDetect="16#ffff_ffff_ffff_ffff"/>
451
+ <SafetyInfo/>
452
+ <DataTypes>
453
+ <DataType Name="Motor" Family="NoFamily" Class="User">
454
+ <Members>
455
+ <Member Name="Status" DataType="Status" Dimension="0" Radix="NullType" Hidden="false" ExternalAccess="Read/Write"/>
456
+ <Member Name="Speed" DataType="INT" Dimension="0" Radix="Decimal" Hidden="false" ExternalAccess="Read/Write"/>
457
+ </Members>
458
+ </DataType>
459
+ <DataType Name="Status" Family="NoFamily" Class="User">
460
+ <Members>
461
+ <Member Name="ZZZZZZZZZZStatus0" DataType="SINT" Dimension="0" Radix="Decimal" Hidden="true" ExternalAccess="Read/Write"/>
462
+ <Member Name="Running" DataType="BIT" Dimension="0" Radix="Decimal" Hidden="false" Target="ZZZZZZZZZZStatus0" BitNumber="0" ExternalAccess="Read/Write"/>
463
+ <Member Name="Faulty" DataType="BIT" Dimension="0" Radix="Decimal" Hidden="false" Target="ZZZZZZZZZZStatus0" BitNumber="1" ExternalAccess="Read/Write"/>
464
+ </Members>
465
+ </DataType>
466
+ </DataTypes>
467
+ <Modules>
468
+ <Module Name="Local" CatalogNumber="1756-L81E" Vendor="1" ProductType="14" ProductCode="164" Major="38" Minor="11" ParentModule="Local" ParentModPortId="1" Inhibited="false" MajorFault="true"
469
+ >
470
+ <EKey State="Disabled"/>
471
+ <Ports>
472
+ <Port Id="1" Address="0" Type="ICP" Upstream="false">
473
+ <Bus Size="7"/>
474
+ </Port>
475
+ <Port Id="2" Type="Ethernet" Upstream="false">
476
+ <Bus/>
477
+ </Port>
478
+ </Ports>
479
+ </Module>
480
+ </Modules>
481
+ <AddOnInstructionDefinitions/>
482
+ <Tags>
483
+ <Tag Name="Integer_tag" TagType="Base" DataType="DINT" Radix="Decimal" Constant="false" ExternalAccess="Read Only" OpcUaAccess="None">
484
+ <Data Format="L5K">
485
+ <![CDATA[0]]>
486
+ </Data>
487
+ <Data Format="Decorated">
488
+ <DataValue DataType="DINT" Radix="Decimal" Value="0"/>
489
+ </Data>
490
+ </Tag>
491
+ <Tag Name="Motor1" TagType="Base" DataType="Motor" Constant="false" ExternalAccess="Read Only" OpcUaAccess="None">
492
+ <Data Format="L5K">
493
+ <![CDATA[[[0],0]]]>
494
+ </Data>
495
+ <Data Format="Decorated">
496
+ <Structure DataType="Motor">
497
+ <StructureMember Name="Status" DataType="Status">
498
+ <DataValueMember Name="Running" DataType="BOOL" Value="0"/>
499
+ <DataValueMember Name="Faulty" DataType="BOOL" Value="0"/>
500
+ </StructureMember>
501
+ <DataValueMember Name="Speed" DataType="INT" Radix="Decimal" Value="0"/>
502
+ </Structure>
503
+ </Data>
504
+ </Tag>
505
+ </Tags>
506
+ <Programs>
507
+ <Program Name="MainProgram" TestEdits="false" MainRoutineName="MainRoutine" Disabled="false" UseAsFolder="false">
508
+ <Tags/>
509
+ <Routines>
510
+ <Routine Name="MainRoutine" Type="RLL"/>
511
+ </Routines>
512
+ </Program>
513
+ </Programs>
514
+ <Tasks>
515
+ <Task Name="MainTask" Type="CONTINUOUS" Priority="10" Watchdog="500" DisableUpdateOutputs="false" InhibitTask="false" SynchronizeRedundancyDataDisabled="false">
516
+ <ScheduledPrograms>
517
+ <ScheduledProgram Name="MainProgram"/>
518
+ </ScheduledPrograms>
519
+ </Task>
520
+ </Tasks>
521
+ <CST MasterID="0"/>
522
+ <WallClockTime LocalTimeAdjustment="0" TimeZone="0"/>
523
+ <Trends/>
524
+ <TimeSynchronize Priority1="128" Priority2="128" PTPEnable="false"/>
525
+ <EthernetPorts>
526
+ <EthernetPort Port="1" Label="1" PortEnabled="true"/>
527
+ </EthernetPorts>
528
+ <OpcUaInfo EnabledPorts=""/>
529
+ </Controller>
530
+ </RSLogix5000Content>
531
+ ```
@@ -0,0 +1,150 @@
1
+ # DialogBox
2
+
3
+ DialogBoxes are windows that can be opened from a UI session to display additional information, gather user input, or provide configuration options. They are defined as `DialogType` objects in the project and can be opened using the `UICommands.OpenDialog()` method.
4
+
5
+ > [!NOTE]
6
+ > DialogBoxes can only be displayed at runtime.
7
+
8
+ ## Opening a DialogBox
9
+
10
+ The `UICommands.OpenDialog()` method opens a dialog (modal window) and associates it with a specific UI session. It has two overloads:
11
+ - `OpenDialog(IUANode parentItem, DialogType dialogType, NodeId aliasNode = null)` - opens a dialog and binds a single alias node
12
+ - `OpenDialog(IUANode parentItem, DialogType dialogType, NodeId[] aliasNodes)` - opens a dialog and binds multiple alias nodes
13
+
14
+ The `parentItem` must be a UI `Item` or `Window` to determine which session receives the dialog.
15
+
16
+ ### Basic Example
17
+
18
+ ```csharp
19
+ [ExportMethod]
20
+ public void OpenMyDialogBox()
21
+ {
22
+ // Get the DialogBox type definition
23
+ var myDialogType = (DialogType)Project.Current.Get("UI/Templates/DialogBox1");
24
+
25
+ // DialogBoxes need a graphical container as parent to bind to the correct session
26
+ var parentPanel = (FTOptix.UI.Panel)Owner;
27
+
28
+ // Open the dialog without alias bindings
29
+ UICommands.OpenDialog(parentPanel, myDialogType);
30
+ }
31
+ ```
32
+
33
+ ### Pass a Single Alias Node
34
+
35
+ Alias nodes are OPC UA references that the dialog can use to access objects. This is useful for passing data or objects to the dialog.
36
+
37
+ ```csharp
38
+ [ExportMethod]
39
+ public void OpenDialogWithAlias()
40
+ {
41
+ var dialogType = (DialogType)Project.Current.Get("UI/Templates/ConfigDialog");
42
+ var configObject = Project.Current.Get("Objects/CurrentConfig");
43
+
44
+ // Bind a single alias node - the dialog can access it through the alias
45
+ UICommands.OpenDialog((FTOptix.UI.Panel)Owner, dialogType, configObject.NodeId);
46
+ }
47
+ ```
48
+
49
+ ### Pass Multiple Alias Nodes
50
+
51
+ You can pass an array of alias nodes to provide the dialog with access to multiple objects.
52
+
53
+ ```csharp
54
+ [ExportMethod]
55
+ public void OpenDialogWithMultipleAliases()
56
+ {
57
+ var dialogType = (DialogType)Project.Current.Get("UI/Templates/DetailDialog");
58
+ var primaryData = Project.Current.Get("Objects/PrimaryData");
59
+ var secondaryData = Project.Current.Get("Objects/SecondaryData");
60
+ var settings = Project.Current.Get("Objects/Settings");
61
+
62
+ // Create an array of alias nodes
63
+ NodeId[] aliasNodes = new NodeId[]
64
+ {
65
+ primaryData.NodeId,
66
+ secondaryData.NodeId,
67
+ settings.NodeId
68
+ };
69
+
70
+ // Open the dialog with multiple alias bindings
71
+ UICommands.OpenDialog((FTOptix.UI.Panel)Owner, dialogType, aliasNodes);
72
+ }
73
+ ```
74
+
75
+ ### Open a DialogBox on all sessions (native and web)
76
+
77
+ ```csharp
78
+ [ExportMethod]
79
+ public void OpenDialogBox(string DialogBoxName, NodeId[] AliasArray = null)
80
+ {
81
+ DialogType dialogBox = (DialogType)Project.Current.Get($"UI/Screens/{DialogBoxName}");
82
+
83
+ // Open dialog on Native Presentation Engine
84
+ var nativePresentationEngine = Project.Current.Get("UI/NativePresentationEngine");
85
+ var nativePresentationEngineSessions = nativePresentationEngine.Get("Sessions");
86
+ var nativePresentationEngineSession = nativePresentationEngineSessions.Children[0]; // Native PE only has one session, so get the first one
87
+ var nativePresentationEngineWindow = nativePresentationEngineSession.Get("UIRoot");
88
+ UICommands.OpenDialog(nativePresentationEngineWindow, dialogBox, AliasArray);
89
+
90
+ // Open dialog on Web Presentation Engine (may have multiple sessions)
91
+ var webPresentationEngine = Project.Current.Get("UI/WebPresentationEngine");
92
+ var webPresentationEngineSessions = webPresentationEngine.Get("Sessions");
93
+ foreach (var webPresentationEngineSession in webPresentationEngineSessions.Children)
94
+ {
95
+ var webPresentationEngineWindow = webPresentationEngineSession.Get("UIRoot");
96
+ if (webPresentationEngineWindow != null)
97
+ {
98
+ UICommands.OpenDialog(webPresentationEngineWindow, dialogBox, AliasArray);
99
+ }
100
+ }
101
+ }
102
+ ```
103
+
104
+ ## Closing a DialogBox
105
+
106
+ ### Close all DialogBoxes in the current session
107
+
108
+ > [!TIP]
109
+ > The following snippet must be placed in a session-based object (e.g. the `MainWindow` of a project).
110
+
111
+ ```csharp
112
+ [ExportMethod]
113
+ public void CloseAllDialogs()
114
+ {
115
+ // DialogBoxes are children of the current Session, so iterate through
116
+ // the children of UIRoot to find and close all open dialogs
117
+ var uiRoot = Session.Get("UIRoot");
118
+ foreach (Dialog dialog in uiRoot.Children.OfType<Dialog>().ToList())
119
+ {
120
+ dialog.Close();
121
+ }
122
+ }
123
+ ```
124
+
125
+ ### Close a specific DialogBox
126
+
127
+ ```csharp
128
+ [ExportMethod]
129
+ public void CloseMyDialog()
130
+ {
131
+ // Get reference to a specific dialog and close it
132
+ var myDialog = (Dialog)Session.Get("UIRoot/MyDialogBox");
133
+ if (myDialog != null)
134
+ {
135
+ myDialog.Close();
136
+ }
137
+ }
138
+ ```
139
+
140
+ ### Close a DropDownButton
141
+
142
+ ```csharp
143
+ /// <summary>
144
+ /// Close a DropDownButton UI widget by calling its Close method.
145
+ /// Input: assume `Owner` is the DropDownButton or that the code can access it via Owner.
146
+ /// </summary>
147
+ var dropDownButton = (DropDownButton)Owner;
148
+ // Call the Close method exposed by the widget
149
+ dropDownButton.ExecuteMethod("Close");
150
+ ```