@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.
- package/CHANGELOG.md +52 -0
- package/README.md +9 -8
- package/cordis.patch.yml +1 -1
- package/entries/netlogic.js +266 -0
- package/entries/optix.js +13 -0
- package/package.json +10 -10
- package/vendor/l5x/SKILL.md +27 -7
- package/vendor/l5x/lib/engine/change-set.d.ts +9 -1
- package/vendor/l5x/lib/engine/change-set.js +32 -7
- package/vendor/l5x/lib/engine/documentation.d.ts +58 -0
- package/vendor/l5x/lib/engine/documentation.js +237 -0
- package/vendor/l5x/lib/engine/instructions.d.ts +50 -0
- package/vendor/l5x/lib/engine/instructions.js +107 -0
- package/vendor/l5x/lib/engine/ladder.d.ts +74 -0
- package/vendor/l5x/lib/engine/ladder.js +209 -0
- package/vendor/l5x/lib/index.d.ts +1 -0
- package/vendor/l5x/lib/index.js +3 -1
- package/vendor/l5x/lib/model/routines.js +6 -1
- package/vendor/l5x/lib/session.d.ts +20 -0
- package/vendor/l5x/lib/session.js +36 -0
- package/vendor/l5x/lib/tools/document.d.ts +18 -0
- package/vendor/l5x/lib/tools/document.js +119 -0
- package/vendor/l5x/lib/tools/drafts.js +109 -3
- package/vendor/optix/SKILL.md +68 -0
- package/vendor/optix/netlogic/SOURCE.json +12 -0
- package/vendor/optix/netlogic/index.json +1987 -0
- package/vendor/optix/netlogic/pages/accessing-project-nodes.md +113 -0
- package/vendor/optix/netlogic/pages/advanced-svg.md +124 -0
- package/vendor/optix/netlogic/pages/alarming.md +489 -0
- package/vendor/optix/netlogic/pages/async-tasks.md +236 -0
- package/vendor/optix/netlogic/pages/audit-signature.md +91 -0
- package/vendor/optix/netlogic/pages/colors.md +122 -0
- package/vendor/optix/netlogic/pages/companion-specs.md +77 -0
- package/vendor/optix/netlogic/pages/creating-objects.md +370 -0
- package/vendor/optix/netlogic/pages/database-interaction.md +437 -0
- package/vendor/optix/netlogic/pages/datagrids.md +123 -0
- package/vendor/optix/netlogic/pages/debugging-tips.md +605 -0
- package/vendor/optix/netlogic/pages/designtime-tags-import.md +531 -0
- package/vendor/optix/netlogic/pages/dialog-boxes.md +150 -0
- package/vendor/optix/netlogic/pages/dispatch-events.md +200 -0
- package/vendor/optix/netlogic/pages/dynamic-links.md +825 -0
- package/vendor/optix/netlogic/pages/element-access.md +1208 -0
- package/vendor/optix/netlogic/pages/engineering-units.md +298 -0
- package/vendor/optix/netlogic/pages/events.md +340 -0
- package/vendor/optix/netlogic/pages/execute-command.md +202 -0
- package/vendor/optix/netlogic/pages/fto-studio-cli.md +99 -0
- package/vendor/optix/netlogic/pages/good-practices.md +50 -0
- package/vendor/optix/netlogic/pages/information-model.md +89 -0
- package/vendor/optix/netlogic/pages/log-output.md +22 -0
- package/vendor/optix/netlogic/pages/managing-aliases.md +22 -0
- package/vendor/optix/netlogic/pages/manipulate-nodes.md +72 -0
- package/vendor/optix/netlogic/pages/mqtt.md +240 -0
- package/vendor/optix/netlogic/pages/netlogic-lifecycle.md +270 -0
- package/vendor/optix/netlogic/pages/netlogic-overview.md +155 -0
- package/vendor/optix/netlogic/pages/opcua.md +325 -0
- package/vendor/optix/netlogic/pages/plc-tags.md +219 -0
- package/vendor/optix/netlogic/pages/queries.md +1297 -0
- package/vendor/optix/netlogic/pages/random-generation.md +90 -0
- package/vendor/optix/netlogic/pages/recipes.md +375 -0
- package/vendor/optix/netlogic/pages/recipex.md +2383 -0
- package/vendor/optix/netlogic/pages/regex.md +15 -0
- package/vendor/optix/netlogic/pages/register-observers.md +346 -0
- package/vendor/optix/netlogic/pages/reports.md +141 -0
- package/vendor/optix/netlogic/pages/resource-uri.md +308 -0
- package/vendor/optix/netlogic/pages/runtime-tags-import.md +280 -0
- package/vendor/optix/netlogic/pages/serial-port.md +357 -0
- package/vendor/optix/netlogic/pages/sessions.md +58 -0
- package/vendor/optix/netlogic/pages/system-node.md +153 -0
- package/vendor/optix/netlogic/pages/template-library.md +127 -0
- package/vendor/optix/netlogic/pages/threading.md +236 -0
- package/vendor/optix/netlogic/pages/translations.md +417 -0
- package/vendor/optix/netlogic/pages/trends.md +128 -0
- package/vendor/optix/netlogic/pages/ui-animations.md +115 -0
- package/vendor/optix/netlogic/pages/users-groups.md +416 -0
- package/vendor/optix/netlogic/pages/variables-formatting.md +16 -0
- package/vendor/optix/netlogic/pages/variables-interaction.md +557 -0
- package/vendor/optix/netlogic/pages/variables-structure.md +155 -0
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
# Triggering events to the FactoryTalk Optix core
|
|
2
|
+
|
|
3
|
+
> [!WARNING]
|
|
4
|
+
> This page describes low-level features and should be used with caution as they can potentially lead to unexpected results or even break your project.
|
|
5
|
+
> These features are not officially supported and may be subject to changes in future releases.
|
|
6
|
+
|
|
7
|
+
> [!NOTE]
|
|
8
|
+
> Events can only be dispatched at runtime.
|
|
9
|
+
|
|
10
|
+
## Introduction to OPC/UA Events
|
|
11
|
+
|
|
12
|
+
OPC Unified Architecture (OPC UA) is a machine-to-machine communication protocol for industrial automation developed by the OPC Foundation. One of the key features of OPC UA is its ability to handle events. Events in OPC UA are notifications about changes or occurrences within the system that are of interest to clients.
|
|
13
|
+
|
|
14
|
+
### What are OPC/UA Events?
|
|
15
|
+
|
|
16
|
+
OPC UA events provide a mechanism for servers to notify clients about significant changes or occurrences. These events can be anything from simple state changes to complex alarms and conditions. Events are used to inform clients about changes in the system without the need for constant polling, making the communication more efficient.
|
|
17
|
+
|
|
18
|
+
### Types of Events
|
|
19
|
+
|
|
20
|
+
OPC UA defines several types of events, including:
|
|
21
|
+
|
|
22
|
+
- **Simple Events**: Basic notifications about changes or occurrences.
|
|
23
|
+
- **Condition Events**: Notifications about conditions that have a state and can change over time.
|
|
24
|
+
- **Alarm Events**: Special types of condition events that indicate abnormal or critical conditions.
|
|
25
|
+
|
|
26
|
+
### Event Model
|
|
27
|
+
|
|
28
|
+
The OPC UA event model is based on the concept of event types and event instances. Event types define the structure and semantics of events, while event instances are actual occurrences of these events. The event model allows for the creation of custom event types to suit specific application needs.
|
|
29
|
+
|
|
30
|
+
### References to Specifications
|
|
31
|
+
|
|
32
|
+
For more detailed information about OPC UA events, refer to the following OPC Foundation specifications:
|
|
33
|
+
|
|
34
|
+
- [OPC Unified Architecture, Part 3: Address Space Model](https://opcfoundation.org/developer-tools/specifications-unified-architecture/part-3-address-space-model/)
|
|
35
|
+
- [OPC Unified Architecture, Part 5: Information Model](https://opcfoundation.org/developer-tools/specifications-unified-architecture/part-5-information-model/)
|
|
36
|
+
- [OPC Unified Architecture, Part 9: Alarms and Conditions](https://opcfoundation.org/developer-tools/specifications-unified-architecture/part-9-alarms-conditions/)
|
|
37
|
+
|
|
38
|
+
These documents provide comprehensive details on the structure, types, and handling of events in OPC UA.
|
|
39
|
+
|
|
40
|
+
## Dispatching an OPC/UA event
|
|
41
|
+
|
|
42
|
+
> [!WARNING]
|
|
43
|
+
> Events are not directly supported in the FactoryTalk Optix IDE, and the code provided here is an example of how to manually trigger them using custom logic. This code is for reference only and should be adapted to your specific use case.
|
|
44
|
+
|
|
45
|
+
### UserSessionEvent
|
|
46
|
+
|
|
47
|
+
This event can be used to trigger custom messages to the UserSessionEvent logger, for example to notify about expiring passwords and more
|
|
48
|
+
|
|
49
|
+
#### 1. Creating the dispatch method
|
|
50
|
+
|
|
51
|
+
```csharp
|
|
52
|
+
[ExportMethod]
|
|
53
|
+
public void TriggerUserSessionEvent(object[] inputArgs)
|
|
54
|
+
{
|
|
55
|
+
// Convert input arguments to the expected types
|
|
56
|
+
var sourceName = (string) inputArgs[0];
|
|
57
|
+
var sourceNode = (NodeId) inputArgs[1];
|
|
58
|
+
var clientUserId = (string) inputArgs[2];
|
|
59
|
+
var status = (bool) inputArgs[3];
|
|
60
|
+
var message = new LocalizedText((string) inputArgs[4], "en-US");
|
|
61
|
+
|
|
62
|
+
// Get the UserSessionEvent object type
|
|
63
|
+
var userSessionEvent = (IUAObjectType) InformationModel.Get(FTOptix.Core.ObjectTypes.UserSessionEvent);
|
|
64
|
+
|
|
65
|
+
// Create a list to store the event arguments
|
|
66
|
+
List<object> argumentList = [];
|
|
67
|
+
if (userSessionEvent.EventArguments != null)
|
|
68
|
+
{
|
|
69
|
+
argumentList.AddRange(new object[userSessionEvent.EventArguments.GetFields().Count]);
|
|
70
|
+
foreach (var field in userSessionEvent.EventArguments.GetFields())
|
|
71
|
+
{
|
|
72
|
+
// Set the field value based on the field name
|
|
73
|
+
object fieldValue = field switch
|
|
74
|
+
{
|
|
75
|
+
"EventId" => GenerateEventIdFromNodeId((Guid) Session.NodeId.Id),
|
|
76
|
+
"EventType" => FTOptix.Core.ObjectTypes.UserSessionEvent,
|
|
77
|
+
"SourceName" => sourceName,
|
|
78
|
+
"SourceNode" => sourceNode,
|
|
79
|
+
"ClientUserId" => clientUserId,
|
|
80
|
+
"Status" => status,
|
|
81
|
+
"Message" => message,
|
|
82
|
+
"Time" => DateTime.Now,
|
|
83
|
+
"Severity" => new Random().Next(1, 500),
|
|
84
|
+
_ => null
|
|
85
|
+
};
|
|
86
|
+
if (fieldValue != null)
|
|
87
|
+
{
|
|
88
|
+
userSessionEvent.EventArguments.SetFieldValue(argumentList, field, fieldValue);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
// Dispatch the event to the Server object
|
|
92
|
+
LogicObject.Context.GetObject(OpcUa.Objects.Server).DispatchUAEvent(FTOptix.Core.ObjectTypes.UserSessionEvent, argumentList.AsReadOnly());
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
public static ByteString GenerateEventIdFromNodeId(Guid nodeId)
|
|
97
|
+
{
|
|
98
|
+
string baseString = nodeId.ToString() + DateTime.UtcNow.Ticks.ToString();
|
|
99
|
+
using SHA256 sha256 = SHA256.Create();
|
|
100
|
+
byte[] hashBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(baseString));
|
|
101
|
+
return new ByteString(hashBytes);
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
#### 2. Triggering the event
|
|
106
|
+
|
|
107
|
+
```csharp
|
|
108
|
+
|
|
109
|
+
[ExportMethod]
|
|
110
|
+
public void TriggerEvent()
|
|
111
|
+
{
|
|
112
|
+
DispatchEventToCore(Session.User.BrowseName, false, "Custom message triggered from a button");
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
private void DispatchEventToCore(string username, bool successful, string message)
|
|
116
|
+
{
|
|
117
|
+
// Get the EventDispatcher NetLogic
|
|
118
|
+
// This is the NetLogic object that dispatches events to the FactoryTalk Optix core
|
|
119
|
+
// as created in the previous section
|
|
120
|
+
var eventsDispatcherLogic = Project.Current.GetObject("NetLogic/EventsDispatcher");
|
|
121
|
+
if (eventsDispatcherLogic == null)
|
|
122
|
+
{
|
|
123
|
+
Log.Error("LoginButtonLogic", "EventsDispatcher NetLogic not found");
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Create the input arguments for the event
|
|
128
|
+
// The arguments are passed as an object array, to find the list of arguments
|
|
129
|
+
// and the expected values, you can use an EventLogger object and generate
|
|
130
|
+
// an event to see the expected arguments
|
|
131
|
+
var inputArgs = new object[]
|
|
132
|
+
{
|
|
133
|
+
"LoginForm", // SourceName -> The friendly name of the source of the event
|
|
134
|
+
Owner.NodeId, // SourceNode -> The NodeId of the source of the event
|
|
135
|
+
username, // ClientUserId -> The user associated with the event
|
|
136
|
+
successful, // Status -> The status of the event (boolean)
|
|
137
|
+
message // Message -> The message associated with the event
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
// Trigger the event
|
|
141
|
+
eventsDispatcherLogic.ExecuteMethod("TriggerUserSessionEvent", [inputArgs]);
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### AlarmConditionEvent
|
|
146
|
+
|
|
147
|
+
This fires an AlarmConditionEvent with no need to generate the corresponding alarm and can be used to add lines to an AlarmsEventLogger without triggering the actual alarm.
|
|
148
|
+
|
|
149
|
+
```csharp
|
|
150
|
+
[ExportMethod]
|
|
151
|
+
public void TriggerAlarmConditionEvent(string message, UInt16 severity, string sourceName)
|
|
152
|
+
{
|
|
153
|
+
// Convert input arguments to the expected types
|
|
154
|
+
var sourceNode = LogicObject.NodeId;
|
|
155
|
+
var eventMessage = new LocalizedText(message, "en-US");
|
|
156
|
+
|
|
157
|
+
// Get the UserSessionEvent object type
|
|
158
|
+
var alarmConditionEvent = (IUAObjectType)InformationModel.Get(OpcUa.ObjectTypes.AlarmConditionType);
|
|
159
|
+
|
|
160
|
+
// Create a list to store the event arguments
|
|
161
|
+
List<object> argumentList = [];
|
|
162
|
+
if (alarmConditionEvent.EventArguments != null)
|
|
163
|
+
{
|
|
164
|
+
argumentList.AddRange(new object[alarmConditionEvent.EventArguments.GetFields().Count]);
|
|
165
|
+
foreach (var field in alarmConditionEvent.EventArguments.GetFields())
|
|
166
|
+
{
|
|
167
|
+
// Set the field value based on the field name
|
|
168
|
+
object fieldValue = field switch
|
|
169
|
+
{
|
|
170
|
+
"ActiveState_Id" => true,
|
|
171
|
+
"AckedState_Id" => true,
|
|
172
|
+
"ConfirmedState_Id" => true,
|
|
173
|
+
"EventId" => GenerateEventIdFromNodeId(Guid.NewGuid()),
|
|
174
|
+
"ConditionName" => sourceName, // Column "Name" in the AlarmLogger
|
|
175
|
+
"EnabledState_Id" => false,
|
|
176
|
+
"SourceName" => LogicObject.BrowseName, // Column "Source Variable" in the AlarmLogger
|
|
177
|
+
"Time" => DateTime.UtcNow,
|
|
178
|
+
"Message" => eventMessage, // Column "Message" in the AlarmLogger
|
|
179
|
+
"Severity" => severity, // Column "Severity" in the AlarmLogger
|
|
180
|
+
"ConditionId" => sourceNode,
|
|
181
|
+
_ => null
|
|
182
|
+
};
|
|
183
|
+
if (fieldValue != null)
|
|
184
|
+
{
|
|
185
|
+
alarmConditionEvent.EventArguments.SetFieldValue(argumentList, field, fieldValue);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
// Dispatch the event to the Server object
|
|
189
|
+
LogicObject.Context.GetObject(OpcUa.Objects.Server).DispatchUAEvent(OpcUa.ObjectTypes.AlarmConditionType, argumentList.AsReadOnly());
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
public static ByteString GenerateEventIdFromNodeId(Guid nodeId)
|
|
194
|
+
{
|
|
195
|
+
string baseString = nodeId.ToString() + DateTime.UtcNow.Ticks.ToString();
|
|
196
|
+
using SHA256 sha256 = SHA256.Create();
|
|
197
|
+
byte[] hashBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(baseString));
|
|
198
|
+
return new ByteString(hashBytes);
|
|
199
|
+
}
|
|
200
|
+
```
|