node-opcua-address-space 2.182.2 → 2.183.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/api/helpers/argument_list.ts +8 -9
- package/api/helpers/call_helpers.ts +2 -0
- package/api/index.ts +14 -0
- package/api/interfaces/alarms_and_conditions/promote_to_alarm_options.ts +24 -0
- package/api/interfaces/alarms_and_conditions/ua_alarm_condition_ex.ts +33 -0
- package/api/interfaces/alarms_and_conditions/ua_limit_alarm_ex.ts +18 -0
- package/api/loader/nodeset_record.ts +2 -2
- package/api/loader/nodeset_record_applier.ts +1 -0
- package/api/loader/nodeset_xml_producer.ts +5 -1
- package/api/namespace_of.ts +28 -0
- package/dist/api/helpers/argument_list.js +8 -7
- package/dist/api/helpers/argument_list.js.map +1 -1
- package/dist/api/helpers/call_helpers.js +2 -0
- package/dist/api/helpers/call_helpers.js.map +1 -1
- package/dist/api/index.d.ts +11 -0
- package/dist/api/index.js +16 -3
- package/dist/api/index.js.map +1 -1
- package/dist/api/interfaces/alarms_and_conditions/promote_to_alarm_options.d.ts +23 -0
- package/dist/api/interfaces/alarms_and_conditions/promote_to_alarm_options.js +3 -0
- package/dist/api/interfaces/alarms_and_conditions/promote_to_alarm_options.js.map +1 -0
- package/dist/api/interfaces/alarms_and_conditions/ua_alarm_condition_ex.d.ts +31 -0
- package/dist/api/interfaces/alarms_and_conditions/ua_limit_alarm_ex.d.ts +17 -0
- package/dist/api/loader/nodeset_record.d.ts +1 -1
- package/dist/api/loader/nodeset_record.js +1 -1
- package/dist/api/loader/nodeset_record_applier.js +1 -0
- package/dist/api/loader/nodeset_record_applier.js.map +1 -1
- package/dist/api/loader/nodeset_xml_producer.js +7 -1
- package/dist/api/loader/nodeset_xml_producer.js.map +1 -1
- package/dist/api/namespace_of.d.ts +23 -0
- package/dist/api/namespace_of.js +29 -0
- package/dist/api/namespace_of.js.map +1 -0
- package/dist/impl/address_space_change_event_tools.js +4 -1
- package/dist/impl/address_space_change_event_tools.js.map +1 -1
- package/dist/impl/address_space_private.d.ts +6 -6
- package/dist/impl/alarms_and_conditions/ua_acknowledgeable_condition_impl.d.ts +7 -0
- package/dist/impl/alarms_and_conditions/ua_acknowledgeable_condition_impl.js +47 -37
- package/dist/impl/alarms_and_conditions/ua_acknowledgeable_condition_impl.js.map +1 -1
- package/dist/impl/alarms_and_conditions/ua_alarm_condition_impl.d.ts +72 -2
- package/dist/impl/alarms_and_conditions/ua_alarm_condition_impl.js +220 -101
- package/dist/impl/alarms_and_conditions/ua_alarm_condition_impl.js.map +1 -1
- package/dist/impl/alarms_and_conditions/ua_condition_impl.d.ts +19 -0
- package/dist/impl/alarms_and_conditions/ua_condition_impl.js +71 -16
- package/dist/impl/alarms_and_conditions/ua_condition_impl.js.map +1 -1
- package/dist/impl/alarms_and_conditions/ua_exclusive_deviation_alarm_impl.d.ts +1 -1
- package/dist/impl/alarms_and_conditions/ua_exclusive_deviation_alarm_impl.js +2 -2
- package/dist/impl/alarms_and_conditions/ua_exclusive_deviation_alarm_impl.js.map +1 -1
- package/dist/impl/alarms_and_conditions/ua_exclusive_limit_alarm_impl.d.ts +2 -2
- package/dist/impl/alarms_and_conditions/ua_exclusive_limit_alarm_impl.js +4 -4
- package/dist/impl/alarms_and_conditions/ua_exclusive_limit_alarm_impl.js.map +1 -1
- package/dist/impl/alarms_and_conditions/ua_limit_alarm_impl.d.ts +13 -2
- package/dist/impl/alarms_and_conditions/ua_limit_alarm_impl.js +21 -5
- package/dist/impl/alarms_and_conditions/ua_limit_alarm_impl.js.map +1 -1
- package/dist/impl/alarms_and_conditions/ua_non_exclusive_deviation_alarm_impl.d.ts +1 -1
- package/dist/impl/alarms_and_conditions/ua_non_exclusive_deviation_alarm_impl.js +2 -2
- package/dist/impl/alarms_and_conditions/ua_non_exclusive_deviation_alarm_impl.js.map +1 -1
- package/dist/impl/alarms_and_conditions/ua_non_exclusive_limit_alarm_impl.d.ts +1 -1
- package/dist/impl/alarms_and_conditions/ua_non_exclusive_limit_alarm_impl.js +2 -2
- package/dist/impl/alarms_and_conditions/ua_non_exclusive_limit_alarm_impl.js.map +1 -1
- package/dist/impl/alarms_and_conditions/ua_off_normal_alarm_impl.d.ts +1 -1
- package/dist/impl/alarms_and_conditions/ua_off_normal_alarm_impl.js +2 -2
- package/dist/impl/alarms_and_conditions/ua_off_normal_alarm_impl.js.map +1 -1
- package/dist/impl/base_node_impl.d.ts +2 -0
- package/dist/impl/base_node_impl.js +28 -0
- package/dist/impl/base_node_impl.js.map +1 -1
- package/dist/impl/base_node_private.d.ts +2 -0
- package/dist/impl/base_node_private.js.map +1 -1
- package/dist/impl/data_access/adjust_datavalue_status_code.d.ts +2 -2
- package/dist/impl/data_access/adjust_datavalue_status_code.js +35 -4
- package/dist/impl/data_access/adjust_datavalue_status_code.js.map +1 -1
- package/dist/impl/data_access/semantics_changed.d.ts +31 -0
- package/dist/impl/data_access/semantics_changed.js +77 -0
- package/dist/impl/data_access/semantics_changed.js.map +1 -0
- package/dist/impl/data_access/ua_multistate_discrete_impl.js +0 -2
- package/dist/impl/data_access/ua_multistate_discrete_impl.js.map +1 -1
- package/dist/impl/data_access/ua_two_state_discrete_impl.js +6 -15
- package/dist/impl/data_access/ua_two_state_discrete_impl.js.map +1 -1
- package/dist/impl/historical_access/read_processed_details_hook.d.ts +22 -0
- package/dist/impl/historical_access/read_processed_details_hook.js +12 -0
- package/dist/impl/historical_access/read_processed_details_hook.js.map +1 -0
- package/dist/impl/namespace_impl.js +2 -4
- package/dist/impl/namespace_impl.js.map +1 -1
- package/dist/impl/ua_object_impl.js +13 -1
- package/dist/impl/ua_object_impl.js.map +1 -1
- package/dist/impl/ua_variable_impl.js +12 -1
- package/dist/impl/ua_variable_impl.js.map +1 -1
- package/dist/tsconfig_base.tsbuildinfo +1 -1
- package/distHelpers/get_address_space_fixture.js +2 -1
- package/distHelpers/get_address_space_fixture.js.map +1 -1
- package/distHelpers/index.d.ts +1 -0
- package/distHelpers/index.js +1 -0
- package/distHelpers/index.js.map +1 -1
- package/distNodeJS/generate_address_space.js +5 -1
- package/distNodeJS/generate_address_space.js.map +1 -1
- package/impl/address_space_change_event_tools.ts +4 -1
- package/impl/address_space_private.ts +5 -17
- package/impl/alarms_and_conditions/ua_acknowledgeable_condition_impl.ts +53 -41
- package/impl/alarms_and_conditions/ua_alarm_condition_impl.ts +262 -111
- package/impl/alarms_and_conditions/ua_condition_impl.ts +94 -20
- package/impl/alarms_and_conditions/ua_exclusive_deviation_alarm_impl.ts +2 -2
- package/impl/alarms_and_conditions/ua_exclusive_limit_alarm_impl.ts +4 -4
- package/impl/alarms_and_conditions/ua_limit_alarm_impl.ts +22 -5
- package/impl/alarms_and_conditions/ua_non_exclusive_deviation_alarm_impl.ts +2 -2
- package/impl/alarms_and_conditions/ua_non_exclusive_limit_alarm_impl.ts +2 -2
- package/impl/alarms_and_conditions/ua_off_normal_alarm_impl.ts +2 -2
- package/impl/base_node_impl.ts +31 -0
- package/impl/base_node_private.ts +2 -0
- package/impl/data_access/adjust_datavalue_status_code.ts +36 -7
- package/impl/data_access/semantics_changed.ts +102 -0
- package/impl/data_access/ua_multistate_discrete_impl.ts +0 -2
- package/impl/data_access/ua_two_state_discrete_impl.ts +6 -16
- package/impl/historical_access/read_processed_details_hook.ts +35 -0
- package/impl/namespace_impl.ts +2 -6
- package/impl/ua_object_impl.ts +13 -1
- package/impl/ua_variable_impl.ts +12 -1
- package/package.json +39 -39
- package/source_nodejs/generate_address_space.ts +6 -1
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @module node-opcua-address-space.AlarmsAndConditions
|
|
3
3
|
*/
|
|
4
4
|
import { isDeepStrictEqual as isEqual } from "node:util";
|
|
5
|
-
import type { BaseNode, INamespace, UAEventType, UAProperty, UAVariable } from "node-opcua-address-space-base";
|
|
5
|
+
import type { BaseNode, INamespace, UAEventType, UAObject, UAProperty, UAVariable } from "node-opcua-address-space-base";
|
|
6
6
|
import { assert } from "node-opcua-assert";
|
|
7
7
|
import { NodeClass } from "node-opcua-data-model";
|
|
8
8
|
import type { DataValue } from "node-opcua-data-value";
|
|
@@ -12,6 +12,7 @@ import { StatusCodes } from "node-opcua-status-code";
|
|
|
12
12
|
import { DataType, type VariantOptions } from "node-opcua-variant";
|
|
13
13
|
import type { ConditionInfo } from "../../api/interfaces/alarms_and_conditions/condition_info_i.js";
|
|
14
14
|
import type { InstantiateAlarmConditionOptions } from "../../api/interfaces/alarms_and_conditions/instantiate_alarm_condition_options.js";
|
|
15
|
+
import type { PromoteToAlarmOptions } from "../../api/interfaces/alarms_and_conditions/promote_to_alarm_options.js";
|
|
15
16
|
import type { UAAlarmConditionEx } from "../../api/interfaces/alarms_and_conditions/ua_alarm_condition_ex.js";
|
|
16
17
|
import type { UAShelvedStateMachineEx } from "../../api/interfaces/state_machine/ua_shelved_state_machine_ex.js";
|
|
17
18
|
import type { UATwoStateVariableEx } from "../../api/ua_two_state_variable_ex.js";
|
|
@@ -23,7 +24,12 @@ import {
|
|
|
23
24
|
} from "../state_machine/ua_shelving_state_machine_ex.js";
|
|
24
25
|
import { _install_TwoStateVariable_machinery } from "../state_machine/ua_two_state_variable.js";
|
|
25
26
|
import { ConditionInfoImpl } from "./condition_info_impl.js";
|
|
26
|
-
import {
|
|
27
|
+
import {
|
|
28
|
+
_initialize_acknowledgeable_condition_node,
|
|
29
|
+
UAAcknowledgeableConditionImpl,
|
|
30
|
+
UAAcknowledgeableConditionImplBase
|
|
31
|
+
} from "./ua_acknowledgeable_condition_impl.js";
|
|
32
|
+
import { _initialize_condition_node, type ConditionInitializationOptions } from "./ua_condition_impl.js";
|
|
27
33
|
|
|
28
34
|
const debugLog = make_debugLog("ua_alarm_condition_impl");
|
|
29
35
|
const doDebug = checkDebugFlag("ua_alarm_condition_impl");
|
|
@@ -62,6 +68,7 @@ export class UAAlarmConditionImplBase extends UAAcknowledgeableConditionImplBase
|
|
|
62
68
|
const addressSpace = namespace.addressSpace;
|
|
63
69
|
// xx assert(Object.prototype.hasOwnProperty.call(options,"conditionOf")); // must provide a conditionOf
|
|
64
70
|
assert(Object.hasOwn(options, "inputNode")); // must provide a inputNode
|
|
71
|
+
assert(options.inputNode, " must provide options.inputNode (NodeId or BaseNode object)");
|
|
65
72
|
const alarmConditionType = addressSpace.findEventType(alarmConditionTypeId);
|
|
66
73
|
|
|
67
74
|
/* c8 ignore next */
|
|
@@ -99,114 +106,8 @@ export class UAAlarmConditionImplBase extends UAAcknowledgeableConditionImplBase
|
|
|
99
106
|
options,
|
|
100
107
|
data
|
|
101
108
|
) as unknown as UAAlarmConditionImpl;
|
|
102
|
-
Object.setPrototypeOf(alarmNode, UAAlarmConditionImpl.prototype);
|
|
103
|
-
|
|
104
|
-
// ----------------------- Install Alarm specifics
|
|
105
|
-
//
|
|
106
|
-
|
|
107
|
-
// Specs 1.03:
|
|
108
|
-
// ActiveState/Id when set to TRUE indicates that the situation the Condition is representing
|
|
109
|
-
// currently exists. When a Condition instance is in the inactive state (ActiveState/Id when set to
|
|
110
|
-
// FALSE) it is representing a situation that has returned to a normal state. The transitions of
|
|
111
|
-
// Conditions to the inactive and Active states are triggered by Server specific actions. Sub-
|
|
112
|
-
// Types of the AlarmConditionType specified later in this document will have sub-state models
|
|
113
|
-
// that further define the Active state. Recommended state names are described in Annex A.
|
|
114
|
-
// install activeState - Mandatory
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* @property activeState
|
|
118
|
-
* @type {UATwoStateVariable}
|
|
119
|
-
*/
|
|
120
|
-
_install_TwoStateVariable_machinery(alarmNode.activeState, {
|
|
121
|
-
falseState: "Inactive",
|
|
122
|
-
trueState: "Active"
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
alarmNode.currentBranch().setActiveState(false);
|
|
126
|
-
|
|
127
|
-
// Specs 1.03:
|
|
128
|
-
/**
|
|
129
|
-
*
|
|
130
|
-
* SuppressState is used internally by a Server to automatically suppress Alarms due to system
|
|
131
|
-
* specific reasons. For example a system may be configured to suppress Alarms that are
|
|
132
|
-
* associated with machinery that is shutdown, such as a low level Alarm for a tank that is
|
|
133
|
-
* currently not in use.
|
|
134
|
-
*
|
|
135
|
-
* @property suppressedState
|
|
136
|
-
* @type UATwoStateVariable
|
|
137
|
-
*/
|
|
138
|
-
if (alarmNode.suppressedState) {
|
|
139
|
-
// install activeState - Optional
|
|
140
|
-
_install_TwoStateVariable_machinery(alarmNode.suppressedState, {
|
|
141
|
-
falseState: "Unsuppressed",
|
|
142
|
-
trueState: "Suppressed"
|
|
143
|
-
});
|
|
144
|
-
}
|
|
145
|
-
// Specs 1.03:
|
|
146
|
-
/**
|
|
147
|
-
* ShelvingState suggests whether an Alarm shall (temporarily) be prevented from being
|
|
148
|
-
* displayed to the user. It is quite often used to block nuisance Alarms.
|
|
149
|
-
*
|
|
150
|
-
* @property shelvingState
|
|
151
|
-
* @type ShelvingStateMachine
|
|
152
|
-
*/
|
|
153
|
-
if (alarmNode.shelvingState) {
|
|
154
|
-
UAShelvedStateMachineExImplBase.promote(alarmNode.shelvingState);
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
// SuppressedOrShelved : Mandatory
|
|
158
|
-
// install suppressedOrShelved automatic detection
|
|
159
|
-
/**
|
|
160
|
-
* The SuppressedState and the ShelvingState together result in the SuppressedOrShelved status of the
|
|
161
|
-
* Condition. When an Alarm is in one of the states, the SuppressedOrShelved property will be set TRUE
|
|
162
|
-
* and this Alarm is then typically not displayed by the Client. State transitions associated with the
|
|
163
|
-
* Alarm do occur, but they are not typically displayed by the Clients as long as the Alarm remains in
|
|
164
|
-
* either the Suppressed or Shelved state.
|
|
165
|
-
* The dataType is Boolean.
|
|
166
|
-
* @property suppressedState
|
|
167
|
-
* @type UAVariable
|
|
168
|
-
*
|
|
169
|
-
*/
|
|
170
|
-
if (alarmNode.suppressedState) {
|
|
171
|
-
alarmNode.suppressedState.on("value_changed", (_newDataValue: DataValue) => {
|
|
172
|
-
_update_suppressedOrShelved(alarmNode);
|
|
173
|
-
});
|
|
174
|
-
}
|
|
175
|
-
if (alarmNode.shelvingState) {
|
|
176
|
-
alarmNode.shelvingState.currentState.on("value_changed", (_newDataValue: DataValue) => {
|
|
177
|
-
_update_suppressedOrShelved(alarmNode);
|
|
178
|
-
});
|
|
179
|
-
}
|
|
180
|
-
_update_suppressedOrShelved(alarmNode);
|
|
181
109
|
|
|
182
|
-
|
|
183
|
-
* The optional Property MaxTimeShelved is used to set the maximum time that an Alarm Condition may be shelved.
|
|
184
|
-
* The value is expressed as duration. Systems can use this Property to prevent permanent Shelving of an Alarm.
|
|
185
|
-
* If this Property is present it will be an upper limit on the duration passed into a TimedShelve Method call.
|
|
186
|
-
* If a value that exceeds the value of this property is passed to the TimedShelve Method,
|
|
187
|
-
* than a BadShelvingTimeOutOfRange error code is returned on the call. If this Property is present it will
|
|
188
|
-
* also be enforced for the OneShotShelved state, in that an Alarm Condition will transition to the Unshelved
|
|
189
|
-
* state from the OneShotShelved state if the duration specified in this Property expires following a
|
|
190
|
-
* OneShotShelve operation without a change of any of the other items associated with the Condition.
|
|
191
|
-
*
|
|
192
|
-
* @property maxTimeShelved
|
|
193
|
-
* @type {UAVariable}
|
|
194
|
-
*/
|
|
195
|
-
if (alarmNode.maxTimeShelved) {
|
|
196
|
-
options.maxTimeShelved = options.maxTimeShelved || 60.0 * 1000; // 60 seconds
|
|
197
|
-
alarmNode.maxTimeShelved.setValueFromSource({
|
|
198
|
-
dataType: "Duration",
|
|
199
|
-
value: options.maxTimeShelved
|
|
200
|
-
});
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
// ---------- install inputNode
|
|
204
|
-
assert(options.inputNode, " must provide options.inputNode (NodeId or BaseNode object)");
|
|
205
|
-
alarmNode.installInputNodeMonitoring(options.inputNode);
|
|
206
|
-
|
|
207
|
-
assert(alarmNode instanceof UAAcknowledgeableConditionImpl);
|
|
208
|
-
assert(alarmNode instanceof UAAlarmConditionImpl);
|
|
209
|
-
return alarmNode;
|
|
110
|
+
return _initialize_alarm_condition_node(alarmNode, options);
|
|
210
111
|
}
|
|
211
112
|
|
|
212
113
|
public dispose(): void {
|
|
@@ -323,10 +224,36 @@ export class UAAlarmConditionImplBase extends UAAcknowledgeableConditionImplBase
|
|
|
323
224
|
this._onInputDataValueChange(dataValue);
|
|
324
225
|
}
|
|
325
226
|
|
|
326
|
-
|
|
227
|
+
/**
|
|
228
|
+
* What the alarm does when the value of its input node changes. Assign to it to give an
|
|
229
|
+
* alarm a state machine of its own, without deriving from anything.
|
|
230
|
+
*
|
|
231
|
+
* @example
|
|
232
|
+
*
|
|
233
|
+
* ```ts
|
|
234
|
+
* const myAlarm = namespace.instantiateAlarmCondition("AlarmConditionType", { ... });
|
|
235
|
+
* myAlarm.onInputDataValueChange = (newValue) => {
|
|
236
|
+
* const tooHot = newValue.value.value > 80;
|
|
237
|
+
* if (tooHot !== myAlarm.activeState.getValue()) {
|
|
238
|
+
* myAlarm.signalNewCondition(tooHot ? "Active" : "Inactive", tooHot, `${newValue.value.value}`);
|
|
239
|
+
* }
|
|
240
|
+
* };
|
|
241
|
+
* ```
|
|
242
|
+
*
|
|
243
|
+
* The default does nothing: a plain AlarmConditionType has no idea what its input means.
|
|
244
|
+
* The alarm types that do (limit alarms, off-normal alarms) override this.
|
|
245
|
+
*/
|
|
246
|
+
public onInputDataValueChange(_newValue: DataValue): void {
|
|
327
247
|
/** */
|
|
328
248
|
}
|
|
329
249
|
|
|
250
|
+
/**
|
|
251
|
+
* @deprecated assign {@link onInputDataValueChange} instead; this delegates to it.
|
|
252
|
+
*/
|
|
253
|
+
protected _onInputDataValueChange(newValue: DataValue): void {
|
|
254
|
+
this.onInputDataValueChange(newValue);
|
|
255
|
+
}
|
|
256
|
+
|
|
330
257
|
/**
|
|
331
258
|
* install mechanism that listen to input node datavalue changes so that alarm status
|
|
332
259
|
* can be automatically updated appropriately.
|
|
@@ -464,7 +391,21 @@ export class UAAlarmConditionImplBase extends UAAcknowledgeableConditionImplBase
|
|
|
464
391
|
this.currentBranch().setActiveState(false);
|
|
465
392
|
this.currentBranch().setAckedState(true);
|
|
466
393
|
}
|
|
394
|
+
/**
|
|
395
|
+
* @deprecated call {@link signalNewCondition} instead; this delegates to it.
|
|
396
|
+
*/
|
|
467
397
|
public _signalNewCondition(stateName: string | null, isActive: boolean, value: string): void {
|
|
398
|
+
this.signalNewCondition(stateName, isActive, value);
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
/**
|
|
402
|
+
* Raise a new condition event for this alarm.
|
|
403
|
+
*
|
|
404
|
+
* Call this only when the condition has actually changed: it throws when the new
|
|
405
|
+
* ConditionInfo is equal to the current one, because raising an event that reports
|
|
406
|
+
* nothing new is a bug in the caller rather than a state the alarm can represent.
|
|
407
|
+
*/
|
|
408
|
+
public signalNewCondition(stateName: string | null, isActive: boolean, value: string): void {
|
|
468
409
|
// xx if(stateName === null) {
|
|
469
410
|
// xx alarm.currentBranch().setActiveState(false);
|
|
470
411
|
// xx alarm.currentBranch().setAckedState(true);
|
|
@@ -480,7 +421,7 @@ export class UAAlarmConditionImplBase extends UAAcknowledgeableConditionImplBase
|
|
|
480
421
|
// `calculateConditionInfo` is reached by the default below. Both work.
|
|
481
422
|
const newConditionInfo = this._calculateConditionInfo(stateName, isActive, value, oldConditionInfo);
|
|
482
423
|
|
|
483
|
-
// detect potential internal bugs due to misused of
|
|
424
|
+
// detect potential internal bugs due to misused of signalNewCondition
|
|
484
425
|
if (isEqual(oldConditionInfo, newConditionInfo)) {
|
|
485
426
|
// c8 ignore next
|
|
486
427
|
if (doDebug) {
|
|
@@ -523,3 +464,213 @@ export class UAAlarmConditionImplBase extends UAAcknowledgeableConditionImplBase
|
|
|
523
464
|
export type UAAlarmConditionImpl = UAAlarmConditionImplBase;
|
|
524
465
|
/** @internal */
|
|
525
466
|
export const UAAlarmConditionImpl = UAAlarmConditionImplBase;
|
|
467
|
+
|
|
468
|
+
/**
|
|
469
|
+
* The part of {@link InstantiateAlarmConditionOptions} that the initialization step below reads.
|
|
470
|
+
*
|
|
471
|
+
* @internal
|
|
472
|
+
*/
|
|
473
|
+
export type AlarmConditionInitializationOptions = ConditionInitializationOptions & {
|
|
474
|
+
maxTimeShelved?: number;
|
|
475
|
+
inputNode?: UAVariable | NodeId;
|
|
476
|
+
};
|
|
477
|
+
|
|
478
|
+
/**
|
|
479
|
+
* The alarm half of the wiring, everything that follows the creation of the node.
|
|
480
|
+
*
|
|
481
|
+
* Shared by {@link UAAlarmConditionImplBase.instantiate} and by {@link promoteToAlarm}, so a node
|
|
482
|
+
* that was created some other way ends up with exactly the same machinery rather than an
|
|
483
|
+
* approximation of it. `inputNode` is optional here because a node being promoted may already
|
|
484
|
+
* carry its InputNode property, or may be given one later.
|
|
485
|
+
*
|
|
486
|
+
* @internal
|
|
487
|
+
*/
|
|
488
|
+
export function _initialize_alarm_condition_node(
|
|
489
|
+
alarmNode: UAAlarmConditionImpl,
|
|
490
|
+
options: AlarmConditionInitializationOptions
|
|
491
|
+
): UAAlarmConditionImpl {
|
|
492
|
+
Object.setPrototypeOf(alarmNode, UAAlarmConditionImpl.prototype);
|
|
493
|
+
|
|
494
|
+
// ----------------------- Install Alarm specifics
|
|
495
|
+
//
|
|
496
|
+
|
|
497
|
+
// Specs 1.03:
|
|
498
|
+
// ActiveState/Id when set to TRUE indicates that the situation the Condition is representing
|
|
499
|
+
// currently exists. When a Condition instance is in the inactive state (ActiveState/Id when set to
|
|
500
|
+
// FALSE) it is representing a situation that has returned to a normal state. The transitions of
|
|
501
|
+
// Conditions to the inactive and Active states are triggered by Server specific actions. Sub-
|
|
502
|
+
// Types of the AlarmConditionType specified later in this document will have sub-state models
|
|
503
|
+
// that further define the Active state. Recommended state names are described in Annex A.
|
|
504
|
+
// install activeState - Mandatory
|
|
505
|
+
|
|
506
|
+
/**
|
|
507
|
+
* @property activeState
|
|
508
|
+
* @type {UATwoStateVariable}
|
|
509
|
+
*/
|
|
510
|
+
_install_TwoStateVariable_machinery(alarmNode.activeState, {
|
|
511
|
+
falseState: "Inactive",
|
|
512
|
+
trueState: "Active"
|
|
513
|
+
});
|
|
514
|
+
|
|
515
|
+
alarmNode.currentBranch().setActiveState(false);
|
|
516
|
+
|
|
517
|
+
// Specs 1.03:
|
|
518
|
+
/**
|
|
519
|
+
*
|
|
520
|
+
* SuppressState is used internally by a Server to automatically suppress Alarms due to system
|
|
521
|
+
* specific reasons. For example a system may be configured to suppress Alarms that are
|
|
522
|
+
* associated with machinery that is shutdown, such as a low level Alarm for a tank that is
|
|
523
|
+
* currently not in use.
|
|
524
|
+
*
|
|
525
|
+
* @property suppressedState
|
|
526
|
+
* @type UATwoStateVariable
|
|
527
|
+
*/
|
|
528
|
+
if (alarmNode.suppressedState) {
|
|
529
|
+
// install activeState - Optional
|
|
530
|
+
_install_TwoStateVariable_machinery(alarmNode.suppressedState, {
|
|
531
|
+
falseState: "Unsuppressed",
|
|
532
|
+
trueState: "Suppressed"
|
|
533
|
+
});
|
|
534
|
+
}
|
|
535
|
+
// Specs 1.03:
|
|
536
|
+
/**
|
|
537
|
+
* ShelvingState suggests whether an Alarm shall (temporarily) be prevented from being
|
|
538
|
+
* displayed to the user. It is quite often used to block nuisance Alarms.
|
|
539
|
+
*
|
|
540
|
+
* @property shelvingState
|
|
541
|
+
* @type ShelvingStateMachine
|
|
542
|
+
*/
|
|
543
|
+
if (alarmNode.shelvingState) {
|
|
544
|
+
UAShelvedStateMachineExImplBase.promote(alarmNode.shelvingState);
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
// SuppressedOrShelved : Mandatory
|
|
548
|
+
// install suppressedOrShelved automatic detection
|
|
549
|
+
/**
|
|
550
|
+
* The SuppressedState and the ShelvingState together result in the SuppressedOrShelved status of the
|
|
551
|
+
* Condition. When an Alarm is in one of the states, the SuppressedOrShelved property will be set TRUE
|
|
552
|
+
* and this Alarm is then typically not displayed by the Client. State transitions associated with the
|
|
553
|
+
* Alarm do occur, but they are not typically displayed by the Clients as long as the Alarm remains in
|
|
554
|
+
* either the Suppressed or Shelved state.
|
|
555
|
+
* The dataType is Boolean.
|
|
556
|
+
* @property suppressedState
|
|
557
|
+
* @type UAVariable
|
|
558
|
+
*
|
|
559
|
+
*/
|
|
560
|
+
if (alarmNode.suppressedState) {
|
|
561
|
+
alarmNode.suppressedState.on("value_changed", (_newDataValue: DataValue) => {
|
|
562
|
+
_update_suppressedOrShelved(alarmNode);
|
|
563
|
+
});
|
|
564
|
+
}
|
|
565
|
+
if (alarmNode.shelvingState) {
|
|
566
|
+
alarmNode.shelvingState.currentState.on("value_changed", (_newDataValue: DataValue) => {
|
|
567
|
+
_update_suppressedOrShelved(alarmNode);
|
|
568
|
+
});
|
|
569
|
+
}
|
|
570
|
+
_update_suppressedOrShelved(alarmNode);
|
|
571
|
+
|
|
572
|
+
/**
|
|
573
|
+
* The optional Property MaxTimeShelved is used to set the maximum time that an Alarm Condition may be shelved.
|
|
574
|
+
* The value is expressed as duration. Systems can use this Property to prevent permanent Shelving of an Alarm.
|
|
575
|
+
* If this Property is present it will be an upper limit on the duration passed into a TimedShelve Method call.
|
|
576
|
+
* If a value that exceeds the value of this property is passed to the TimedShelve Method,
|
|
577
|
+
* than a BadShelvingTimeOutOfRange error code is returned on the call. If this Property is present it will
|
|
578
|
+
* also be enforced for the OneShotShelved state, in that an Alarm Condition will transition to the Unshelved
|
|
579
|
+
* state from the OneShotShelved state if the duration specified in this Property expires following a
|
|
580
|
+
* OneShotShelve operation without a change of any of the other items associated with the Condition.
|
|
581
|
+
*
|
|
582
|
+
* @property maxTimeShelved
|
|
583
|
+
* @type {UAVariable}
|
|
584
|
+
*/
|
|
585
|
+
if (alarmNode.maxTimeShelved) {
|
|
586
|
+
options.maxTimeShelved = options.maxTimeShelved || 60.0 * 1000; // 60 seconds
|
|
587
|
+
alarmNode.maxTimeShelved.setValueFromSource({
|
|
588
|
+
dataType: "Duration",
|
|
589
|
+
value: options.maxTimeShelved
|
|
590
|
+
});
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
// ---------- install inputNode
|
|
594
|
+
if (options.inputNode) {
|
|
595
|
+
alarmNode.installInputNodeMonitoring(options.inputNode);
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
assert(alarmNode instanceof UAAcknowledgeableConditionImpl);
|
|
599
|
+
assert(alarmNode instanceof UAAlarmConditionImpl);
|
|
600
|
+
return alarmNode;
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
/**
|
|
604
|
+
* Give an existing node the behaviour of the alarm its type says it is.
|
|
605
|
+
*
|
|
606
|
+
* A node only becomes a working alarm when `namespace.instantiateAlarmCondition` builds it; a node
|
|
607
|
+
* that arrived any other way - `objectType.instantiate()`, or a nodeset XML - carries the right
|
|
608
|
+
* children but none of the machinery, so `activateAlarm` and `signalNewCondition` are simply not
|
|
609
|
+
* there. This retypes the node in place, keeping its identity in the address space index and every
|
|
610
|
+
* reference already pointing at it, and then runs the same initialization the factory runs.
|
|
611
|
+
*
|
|
612
|
+
* Limit alarms are refused rather than half-promoted: their behaviour lives in
|
|
613
|
+
* UALimitAlarmImpl and its subclasses, and a node wearing the plain alarm prototype would look
|
|
614
|
+
* promoted while ignoring its own limit set points.
|
|
615
|
+
*/
|
|
616
|
+
export function promoteToAlarm(node: UAObject, options?: PromoteToAlarmOptions): UAAlarmConditionEx {
|
|
617
|
+
if (node instanceof UAAlarmConditionImplBase) {
|
|
618
|
+
return node as unknown as UAAlarmConditionImpl; // already promoted
|
|
619
|
+
}
|
|
620
|
+
const addressSpace = node.addressSpace;
|
|
621
|
+
const typeDefinition = node.typeDefinitionObj;
|
|
622
|
+
|
|
623
|
+
const alarmConditionType = addressSpace.findObjectType("AlarmConditionType");
|
|
624
|
+
/* c8 ignore next */
|
|
625
|
+
if (!alarmConditionType) {
|
|
626
|
+
throw new Error("promoteToAlarm: cannot find AlarmConditionType - is the standard nodeset loaded ?");
|
|
627
|
+
}
|
|
628
|
+
if (!typeDefinition || (typeDefinition !== alarmConditionType && !typeDefinition.isSubtypeOf(alarmConditionType))) {
|
|
629
|
+
throw new Error(
|
|
630
|
+
`promoteToAlarm: ${node.browseName.toString()} has type definition ` +
|
|
631
|
+
`${typeDefinition ? typeDefinition.browseName.toString() : "<none>"} ` +
|
|
632
|
+
"which does not derive from AlarmConditionType - only alarms can be promoted"
|
|
633
|
+
);
|
|
634
|
+
}
|
|
635
|
+
const limitAlarmType = addressSpace.findObjectType("LimitAlarmType");
|
|
636
|
+
if (limitAlarmType && (typeDefinition === limitAlarmType || typeDefinition.isSubtypeOf(limitAlarmType))) {
|
|
637
|
+
throw new Error(
|
|
638
|
+
`promoteToAlarm: ${node.browseName.toString()} is a ${typeDefinition.browseName.toString()}, ` +
|
|
639
|
+
"a limit alarm - promoting limit alarms is not supported, use namespace.instantiateLimitAlarm instead"
|
|
640
|
+
);
|
|
641
|
+
}
|
|
642
|
+
// CertificateExpirationAlarmType carries behaviour of its own - promoteToCertificateExpirationAlarm
|
|
643
|
+
// starts an expiry timer and registers a shutdown task. Promoting one here would give it plain
|
|
644
|
+
// alarm behaviour and silently drop that, which is worse than refusing: the node would look
|
|
645
|
+
// promoted and never fire.
|
|
646
|
+
const certificateExpirationAlarmType = addressSpace.findObjectType("CertificateExpirationAlarmType");
|
|
647
|
+
if (
|
|
648
|
+
certificateExpirationAlarmType &&
|
|
649
|
+
(typeDefinition === certificateExpirationAlarmType || typeDefinition.isSubtypeOf(certificateExpirationAlarmType))
|
|
650
|
+
) {
|
|
651
|
+
throw new Error(
|
|
652
|
+
`promoteToAlarm: ${node.browseName.toString()} is a ${typeDefinition.browseName.toString()}, ` +
|
|
653
|
+
"which has its own expiry machinery - use promoteToCertificateExpirationAlarm instead"
|
|
654
|
+
);
|
|
655
|
+
}
|
|
656
|
+
const alarmConditionEventType = addressSpace.findEventType(typeDefinition.nodeId);
|
|
657
|
+
/* c8 ignore next */
|
|
658
|
+
if (!alarmConditionEventType) {
|
|
659
|
+
throw new Error(`promoteToAlarm: cannot find event type for ${typeDefinition.browseName.toString()}`);
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
// conditionSource has to be an own property even when it is absent: the condition
|
|
663
|
+
// initialization tells "no source" from "source not considered" by its presence.
|
|
664
|
+
const initializationOptions: AlarmConditionInitializationOptions = {
|
|
665
|
+
conditionClass: options?.conditionClass,
|
|
666
|
+
conditionName: options?.conditionName || node.browseName.name || undefined,
|
|
667
|
+
conditionSource: options?.conditionSource ?? null,
|
|
668
|
+
inputNode: options?.inputNode,
|
|
669
|
+
maxTimeShelved: options?.maxTimeShelved
|
|
670
|
+
};
|
|
671
|
+
|
|
672
|
+
const conditionNode = node as unknown as UAAlarmConditionImpl;
|
|
673
|
+
_initialize_condition_node(node.namespace, conditionNode, alarmConditionEventType, initializationOptions);
|
|
674
|
+
_initialize_acknowledgeable_condition_node(conditionNode);
|
|
675
|
+
return _initialize_alarm_condition_node(conditionNode, initializationOptions);
|
|
676
|
+
}
|
|
@@ -749,6 +749,40 @@ function UACondition_instantiate(
|
|
|
749
749
|
namespace: options.namespace || namespace
|
|
750
750
|
};
|
|
751
751
|
const conditionNode = conditionType.instantiate(options2) as unknown as UAConditionImpl;
|
|
752
|
+
return _initialize_condition_node(namespace, conditionNode, conditionType, options, data);
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
/**
|
|
756
|
+
* The part of {@link InstantiateConditionOptions} that the initialization step below reads.
|
|
757
|
+
*
|
|
758
|
+
* Named separately so a caller that is wiring an existing node - which has no browseName or
|
|
759
|
+
* parent to give - does not have to invent the creation-time half of the options.
|
|
760
|
+
*
|
|
761
|
+
* @internal
|
|
762
|
+
*/
|
|
763
|
+
export type ConditionInitializationOptions = Pick<
|
|
764
|
+
InstantiateConditionOptions,
|
|
765
|
+
"conditionSource" | "conditionOf" | "conditionClass" | "conditionName"
|
|
766
|
+
>;
|
|
767
|
+
|
|
768
|
+
/**
|
|
769
|
+
* Everything that turns a freshly created node into a working condition.
|
|
770
|
+
*
|
|
771
|
+
* Split out of {@link UACondition_instantiate} so that a node that already exists - one built by
|
|
772
|
+
* `objectType.instantiate` or loaded from a nodeset - can be given the very same wiring without
|
|
773
|
+
* being rebuilt, and so the two routes cannot drift apart.
|
|
774
|
+
*
|
|
775
|
+
* @internal
|
|
776
|
+
*/
|
|
777
|
+
export function _initialize_condition_node(
|
|
778
|
+
namespace: INamespace,
|
|
779
|
+
conditionNode: UAConditionImpl,
|
|
780
|
+
conditionType: UAEventType,
|
|
781
|
+
options: ConditionInitializationOptions,
|
|
782
|
+
data?: Record<string, VariantOptions>
|
|
783
|
+
): UAConditionEx {
|
|
784
|
+
const addressSpace = namespace.addressSpace as AddressSpacePrivate;
|
|
785
|
+
|
|
752
786
|
Object.setPrototypeOf(conditionNode, UAConditionImpl.prototype);
|
|
753
787
|
conditionNode.initialize();
|
|
754
788
|
|
|
@@ -1075,9 +1109,11 @@ function _condition_refresh_method(
|
|
|
1075
1109
|
}
|
|
1076
1110
|
const subscriptionId = inputArguments[0].value;
|
|
1077
1111
|
|
|
1112
|
+
// a rejected argument is answered in the Call result, never thrown: the Call service
|
|
1113
|
+
// turns an exception into Bad_InternalError and the CTT reads that as a broken server
|
|
1078
1114
|
let statusCode = _check_subscription_id_is_valid(subscriptionId, context);
|
|
1079
1115
|
if (statusCode.isNotGood()) {
|
|
1080
|
-
return statusCode;
|
|
1116
|
+
return callback(null, { statusCode });
|
|
1081
1117
|
}
|
|
1082
1118
|
|
|
1083
1119
|
statusCode = _perform_condition_refresh(addressSpace, inputArguments, context);
|
|
@@ -1090,6 +1126,7 @@ function _perform_condition_refresh(addressSpace: AddressSpacePrivate, _inputArg
|
|
|
1090
1126
|
// --- possible StatusCodes:
|
|
1091
1127
|
//
|
|
1092
1128
|
// Bad_SubscriptionIdInvalid See Part 4 for the description of this result code
|
|
1129
|
+
// (checked by the caller, before we get here)
|
|
1093
1130
|
// Bad_RefreshInProgress See Table 74 for the description of this result code
|
|
1094
1131
|
// Bad_UserAccessDenied The Method was not called in the context of the Session
|
|
1095
1132
|
// that owns the Subscription
|
|
@@ -1101,8 +1138,6 @@ function _perform_condition_refresh(addressSpace: AddressSpacePrivate, _inputArg
|
|
|
1101
1138
|
return StatusCodes.BadRefreshInProgress;
|
|
1102
1139
|
}
|
|
1103
1140
|
|
|
1104
|
-
addressSpace._condition_refresh_in_progress = true;
|
|
1105
|
-
|
|
1106
1141
|
const server = context.object?.addressSpace.rootFolder.objects.server;
|
|
1107
1142
|
const refreshStartEventType = addressSpace.findEventType("RefreshStartEventType");
|
|
1108
1143
|
if (!refreshStartEventType) {
|
|
@@ -1113,17 +1148,21 @@ function _perform_condition_refresh(addressSpace: AddressSpacePrivate, _inputArg
|
|
|
1113
1148
|
throw new Error("cannot find RefreshEndEventType");
|
|
1114
1149
|
}
|
|
1115
1150
|
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1151
|
+
addressSpace._condition_refresh_in_progress = true;
|
|
1152
|
+
try {
|
|
1153
|
+
server?.raiseEvent(refreshStartEventType, {});
|
|
1154
|
+
|
|
1155
|
+
const _server = server as unknown as { _conditionRefresh: () => void };
|
|
1156
|
+
// starting from server object ..
|
|
1157
|
+
// evaluated all --> hasNotifier/hasEventSource -> node
|
|
1158
|
+
_server._conditionRefresh();
|
|
1159
|
+
|
|
1160
|
+
server?.raiseEvent(refreshEndEventType, {});
|
|
1161
|
+
} finally {
|
|
1162
|
+
// whatever a condition's event handler throws, the next refresh must not be
|
|
1163
|
+
// answered Bad_RefreshInProgress for ever
|
|
1164
|
+
addressSpace._condition_refresh_in_progress = false;
|
|
1165
|
+
}
|
|
1127
1166
|
|
|
1128
1167
|
return StatusCodes.Good;
|
|
1129
1168
|
}
|
|
@@ -1146,10 +1185,19 @@ function _condition_refresh2_method(
|
|
|
1146
1185
|
debugLog(chalk.cyan.bgWhite(" ConditionType.conditionRefresh2 !"));
|
|
1147
1186
|
}
|
|
1148
1187
|
|
|
1149
|
-
|
|
1150
|
-
|
|
1188
|
+
const subscriptionId = inputArguments[0].value;
|
|
1189
|
+
const monitoredItemId = inputArguments[1].value;
|
|
1151
1190
|
|
|
1152
|
-
|
|
1191
|
+
let statusCode = _check_subscription_id_is_valid(subscriptionId, context);
|
|
1192
|
+
if (statusCode.isNotGood()) {
|
|
1193
|
+
return callback(null, { statusCode });
|
|
1194
|
+
}
|
|
1195
|
+
statusCode = _check_monitored_item_id_is_valid(subscriptionId, monitoredItemId, context);
|
|
1196
|
+
if (statusCode.isNotGood()) {
|
|
1197
|
+
return callback(null, { statusCode });
|
|
1198
|
+
}
|
|
1199
|
+
|
|
1200
|
+
statusCode = _perform_condition_refresh(addressSpace, inputArguments, context);
|
|
1153
1201
|
return callback(null, {
|
|
1154
1202
|
statusCode
|
|
1155
1203
|
});
|
|
@@ -1280,7 +1328,33 @@ function _getCompositeKey(node: BaseNode, key: string): UAVariableImpl {
|
|
|
1280
1328
|
* @param context {Object}
|
|
1281
1329
|
* @private
|
|
1282
1330
|
*/
|
|
1283
|
-
function _check_subscription_id_is_valid(
|
|
1284
|
-
|
|
1285
|
-
|
|
1331
|
+
function _check_subscription_id_is_valid(subscriptionId: number, context: ISessionContext): StatusCode {
|
|
1332
|
+
// Part 9 5.5.7: Bad_SubscriptionIdInvalid when the SubscriptionId is not one of the
|
|
1333
|
+
// calling Session's. A Subscription of another Session is not reachable from this one
|
|
1334
|
+
// (Part 4: SubscriptionIds are Session-scoped), so it gets the same answer.
|
|
1335
|
+
const session = context.session;
|
|
1336
|
+
if (!session || typeof session.getSubscription !== "function") {
|
|
1337
|
+
// no Session behind the call (an in-process caller, a PseudoSession, a unit test):
|
|
1338
|
+
// there is nothing to check the argument against
|
|
1339
|
+
return StatusCodes.Good;
|
|
1340
|
+
}
|
|
1341
|
+
return session.getSubscription(subscriptionId) ? StatusCodes.Good : StatusCodes.BadSubscriptionIdInvalid;
|
|
1342
|
+
}
|
|
1343
|
+
|
|
1344
|
+
/**
|
|
1345
|
+
* ConditionRefresh2 (Part 9 5.5.8): the MonitoredItemId must name a MonitoredItem of the
|
|
1346
|
+
* given Subscription, else Bad_MonitoredItemIdInvalid. Call after
|
|
1347
|
+
* _check_subscription_id_is_valid, which has established that the Subscription is ours.
|
|
1348
|
+
* @private
|
|
1349
|
+
*/
|
|
1350
|
+
function _check_monitored_item_id_is_valid(subscriptionId: number, monitoredItemId: number, context: ISessionContext): StatusCode {
|
|
1351
|
+
const session = context.session;
|
|
1352
|
+
if (!session || typeof session.getSubscription !== "function") {
|
|
1353
|
+
return StatusCodes.Good;
|
|
1354
|
+
}
|
|
1355
|
+
const subscription = session.getSubscription(subscriptionId);
|
|
1356
|
+
if (!subscription) {
|
|
1357
|
+
return StatusCodes.BadSubscriptionIdInvalid;
|
|
1358
|
+
}
|
|
1359
|
+
return subscription.getMonitoredItem(monitoredItemId) ? StatusCodes.Good : StatusCodes.BadMonitoredItemIdInvalid;
|
|
1286
1360
|
}
|
|
@@ -78,14 +78,14 @@ export class UAExclusiveDeviationAlarmImplBase extends UAExclusiveLimitAlarmImpl
|
|
|
78
78
|
DeviationAlarmHelper_install_setpoint.call(this, options);
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
-
public
|
|
81
|
+
public setStateBasedOnInputValue(value: number): void {
|
|
82
82
|
const setpointValue = this.getSetpointValue();
|
|
83
83
|
if (setpointValue === null) {
|
|
84
84
|
return;
|
|
85
85
|
}
|
|
86
86
|
assert(Number.isFinite(setpointValue));
|
|
87
87
|
// call base class implementation
|
|
88
|
-
UAExclusiveLimitAlarmImpl.prototype.
|
|
88
|
+
UAExclusiveLimitAlarmImpl.prototype.setStateBasedOnInputValue.call(this, value - setpointValue);
|
|
89
89
|
}
|
|
90
90
|
}
|
|
91
91
|
/** @internal */
|
|
@@ -62,7 +62,7 @@ export class UAExclusiveLimitAlarmImplBase extends UALimitAlarmImpl implements U
|
|
|
62
62
|
|
|
63
63
|
return alarm as UAExclusiveLimitAlarmImpl;
|
|
64
64
|
}
|
|
65
|
-
public
|
|
65
|
+
public signalNewCondition(stateName: string | null, isActive: boolean, value: string): void {
|
|
66
66
|
assert(stateName === null || typeof isActive === "boolean");
|
|
67
67
|
assert(validState.indexOf(stateName) >= 0, `must have a valid state : ${stateName}`);
|
|
68
68
|
|
|
@@ -75,10 +75,10 @@ export class UAExclusiveLimitAlarmImplBase extends UALimitAlarmImpl implements U
|
|
|
75
75
|
assert(stateName === null);
|
|
76
76
|
this.limitState.setState(stateName);
|
|
77
77
|
}
|
|
78
|
-
super.
|
|
78
|
+
super.signalNewCondition(stateName, isActive, value);
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
-
public
|
|
81
|
+
public setStateBasedOnInputValue(value: number): void {
|
|
82
82
|
assert(Number.isFinite(value));
|
|
83
83
|
let isActive = false;
|
|
84
84
|
|
|
@@ -101,7 +101,7 @@ export class UAExclusiveLimitAlarmImplBase extends UALimitAlarmImpl implements U
|
|
|
101
101
|
}
|
|
102
102
|
|
|
103
103
|
if (state !== oldState) {
|
|
104
|
-
this.
|
|
104
|
+
this.signalNewCondition(state, isActive, value.toFixed(3));
|
|
105
105
|
}
|
|
106
106
|
}
|
|
107
107
|
}
|