node-opcua-address-space 2.76.1 → 2.76.2
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/dist/source/address_space_ts.d.ts +118 -118
- package/dist/source/address_space_ts.js +17 -17
- package/dist/source/continuation_points/continuation_point_manager.d.ts +32 -32
- package/dist/source/continuation_points/continuation_point_manager.js +195 -195
- package/dist/source/helpers/adjust_browse_direction.d.ts +5 -5
- package/dist/source/helpers/adjust_browse_direction.js +11 -11
- package/dist/source/helpers/argument_list.d.ts +33 -33
- package/dist/source/helpers/argument_list.js +258 -258
- package/dist/source/helpers/call_helpers.d.ts +6 -6
- package/dist/source/helpers/call_helpers.js +70 -70
- package/dist/source/helpers/check_event_clause.d.ts +17 -0
- package/dist/source/helpers/check_event_clause.js +53 -0
- package/dist/source/helpers/check_event_clause.js.map +1 -0
- package/dist/source/helpers/coerce_enum_value.d.ts +6 -6
- package/dist/source/helpers/coerce_enum_value.js +33 -33
- package/dist/source/helpers/dump_tools.d.ts +14 -14
- package/dist/source/helpers/dump_tools.js +78 -78
- package/dist/source/helpers/ensure_secure_access.d.ts +9 -9
- package/dist/source/helpers/ensure_secure_access.js +76 -76
- package/dist/source/helpers/make_optionals_map.d.ts +21 -21
- package/dist/source/helpers/make_optionals_map.js +29 -29
- package/dist/source/helpers/multiform_func.d.ts +11 -11
- package/dist/source/helpers/multiform_func.js +75 -75
- package/dist/source/helpers/resolve_opaque_on_address_space.d.ts +3 -3
- package/dist/source/helpers/resolve_opaque_on_address_space.js +36 -36
- package/dist/source/index.d.ts +56 -56
- package/dist/source/index.js +83 -83
- package/dist/source/interfaces/alarms_and_conditions/condition_info_i.d.ts +19 -19
- package/dist/source/interfaces/alarms_and_conditions/condition_info_i.js +2 -2
- package/dist/source/interfaces/alarms_and_conditions/condition_snapshot.d.ts +193 -193
- package/dist/source/interfaces/alarms_and_conditions/condition_snapshot.js +2 -2
- package/dist/source/interfaces/alarms_and_conditions/deviation_stuff.d.ts +12 -12
- package/dist/source/interfaces/alarms_and_conditions/deviation_stuff.js +2 -2
- package/dist/source/interfaces/alarms_and_conditions/install_setpoint_options.d.ts +10 -10
- package/dist/source/interfaces/alarms_and_conditions/install_setpoint_options.js +2 -2
- package/dist/source/interfaces/alarms_and_conditions/instantiate_alarm_condition_options.d.ts +7 -7
- package/dist/source/interfaces/alarms_and_conditions/instantiate_alarm_condition_options.js +2 -2
- package/dist/source/interfaces/alarms_and_conditions/instantiate_condition_options.d.ts +7 -7
- package/dist/source/interfaces/alarms_and_conditions/instantiate_condition_options.js +2 -2
- package/dist/source/interfaces/alarms_and_conditions/instantiate_exclusive_deviation_alarm_options.d.ts +4 -4
- package/dist/source/interfaces/alarms_and_conditions/instantiate_exclusive_deviation_alarm_options.js +2 -2
- package/dist/source/interfaces/alarms_and_conditions/instantiate_exclusive_limit_alarm_options.d.ts +4 -4
- package/dist/source/interfaces/alarms_and_conditions/instantiate_exclusive_limit_alarm_options.js +2 -2
- package/dist/source/interfaces/alarms_and_conditions/instantiate_limit_alarm_options.d.ts +9 -9
- package/dist/source/interfaces/alarms_and_conditions/instantiate_limit_alarm_options.js +2 -2
- package/dist/source/interfaces/alarms_and_conditions/instantiate_non_exclusive_deviation_alarm_options.d.ts +4 -4
- package/dist/source/interfaces/alarms_and_conditions/instantiate_non_exclusive_deviation_alarm_options.js +2 -2
- package/dist/source/interfaces/alarms_and_conditions/instantiate_non_exclusive_limit_alarm_options.d.ts +4 -4
- package/dist/source/interfaces/alarms_and_conditions/instantiate_non_exclusive_limit_alarm_options.js +2 -2
- package/dist/source/interfaces/alarms_and_conditions/instantiate_off_normal_alarm_options.d.ts +20 -20
- package/dist/source/interfaces/alarms_and_conditions/instantiate_off_normal_alarm_options.js +2 -2
- package/dist/source/interfaces/alarms_and_conditions/ua_acknowledgeable_condition_ex.d.ts +23 -23
- package/dist/source/interfaces/alarms_and_conditions/ua_acknowledgeable_condition_ex.js +2 -2
- package/dist/source/interfaces/alarms_and_conditions/ua_alarm_condition_ex.d.ts +32 -32
- package/dist/source/interfaces/alarms_and_conditions/ua_alarm_condition_ex.js +2 -2
- package/dist/source/interfaces/alarms_and_conditions/ua_certificate_expiration_alarm_ex.d.ts +19 -19
- package/dist/source/interfaces/alarms_and_conditions/ua_certificate_expiration_alarm_ex.js +2 -2
- package/dist/source/interfaces/alarms_and_conditions/ua_condition_ex.d.ts +42 -42
- package/dist/source/interfaces/alarms_and_conditions/ua_condition_ex.js +2 -2
- package/dist/source/interfaces/alarms_and_conditions/ua_discrete_alarm_ex.d.ts +7 -7
- package/dist/source/interfaces/alarms_and_conditions/ua_discrete_alarm_ex.js +25 -25
- package/dist/source/interfaces/alarms_and_conditions/ua_exclusive_deviation_alarm_ex.d.ts +5 -5
- package/dist/source/interfaces/alarms_and_conditions/ua_exclusive_deviation_alarm_ex.js +2 -2
- package/dist/source/interfaces/alarms_and_conditions/ua_exclusive_limit_alarm_ex.d.ts +20 -20
- package/dist/source/interfaces/alarms_and_conditions/ua_exclusive_limit_alarm_ex.js +2 -2
- package/dist/source/interfaces/alarms_and_conditions/ua_limit_alarm_ex.d.ts +26 -26
- package/dist/source/interfaces/alarms_and_conditions/ua_limit_alarm_ex.js +2 -2
- package/dist/source/interfaces/alarms_and_conditions/ua_non_exclusive_deviation_alarm_ex.d.ts +8 -8
- package/dist/source/interfaces/alarms_and_conditions/ua_non_exclusive_deviation_alarm_ex.js +2 -2
- package/dist/source/interfaces/alarms_and_conditions/ua_non_exclusive_limit_alarm_ex.d.ts +10 -10
- package/dist/source/interfaces/alarms_and_conditions/ua_non_exclusive_limit_alarm_ex.js +2 -2
- package/dist/source/interfaces/data_access/ua_multistate_discrete_ex.d.ts +21 -21
- package/dist/source/interfaces/data_access/ua_multistate_discrete_ex.js +2 -2
- package/dist/source/interfaces/data_access/ua_multistate_value_discrete_ex.d.ts +24 -24
- package/dist/source/interfaces/data_access/ua_multistate_value_discrete_ex.js +2 -2
- package/dist/source/interfaces/data_access/ua_two_state_discrete_ex.d.ts +12 -12
- package/dist/source/interfaces/data_access/ua_two_state_discrete_ex.js +2 -2
- package/dist/source/interfaces/data_access/ua_y_array_item_ex.d.ts +8 -8
- package/dist/source/interfaces/data_access/ua_y_array_item_ex.js +2 -2
- package/dist/source/interfaces/state_machine/ua_exclusive_limit_state_machine_type_ex.d.ts +12 -12
- package/dist/source/interfaces/state_machine/ua_exclusive_limit_state_machine_type_ex.js +2 -2
- package/dist/source/interfaces/state_machine/ua_finite_state_machine_type.d.ts +49 -49
- package/dist/source/interfaces/state_machine/ua_finite_state_machine_type.js +2 -2
- package/dist/source/interfaces/state_machine/ua_program_state_machine_type.d.ts +11 -11
- package/dist/source/interfaces/state_machine/ua_program_state_machine_type.js +2 -2
- package/dist/source/interfaces/state_machine/ua_shelved_state_machine_ex.d.ts +30 -30
- package/dist/source/interfaces/state_machine/ua_shelved_state_machine_ex.js +2 -2
- package/dist/source/interfaces/state_machine/ua_state_machine_type.d.ts +222 -222
- package/dist/source/interfaces/state_machine/ua_state_machine_type.js +2 -2
- package/dist/source/interfaces/state_machine/ua_transition_ex.d.ts +6 -6
- package/dist/source/interfaces/state_machine/ua_transition_ex.js +2 -2
- package/dist/source/interfaces/ua_subscription_diagnostics_variable_ex.d.ts +8 -8
- package/dist/source/interfaces/ua_subscription_diagnostics_variable_ex.js +2 -2
- package/dist/source/loader/decode_xml_extension_object.d.ts +6 -6
- package/dist/source/loader/decode_xml_extension_object.js +71 -71
- package/dist/source/loader/ensure_datatype_extracted.d.ts +5 -5
- package/dist/source/loader/ensure_datatype_extracted.js +45 -45
- package/dist/source/loader/generateAddressSpaceRaw.d.ts +10 -10
- package/dist/source/loader/generateAddressSpaceRaw.js +45 -45
- package/dist/source/loader/load_nodeset2.d.ts +16 -16
- package/dist/source/loader/load_nodeset2.js +1461 -1461
- package/dist/source/loader/make_semver_compatible.d.ts +6 -6
- package/dist/source/loader/make_semver_compatible.js +25 -25
- package/dist/source/loader/make_xml_extension_object_parser.d.ts +28 -28
- package/dist/source/loader/make_xml_extension_object_parser.js +325 -325
- package/dist/source/loader/namespace_post_step.d.ts +10 -10
- package/dist/source/loader/namespace_post_step.js +61 -61
- package/dist/source/loader/register_node_promoter.d.ts +2 -2
- package/dist/source/loader/register_node_promoter.js +9 -9
- package/dist/source/namespace.d.ts +6 -6
- package/dist/source/namespace.js +2 -2
- package/dist/source/namespace_alarm_and_condition.d.ts +32 -32
- package/dist/source/namespace_alarm_and_condition.js +2 -2
- package/dist/source/namespace_data_access.d.ts +42 -42
- package/dist/source/namespace_data_access.js +2 -2
- package/dist/source/namespace_machine_state.d.ts +7 -7
- package/dist/source/namespace_machine_state.js +2 -2
- package/dist/source/pseudo_session.d.ts +55 -55
- package/dist/source/pseudo_session.js +203 -203
- package/dist/source/session_context.d.ts +111 -111
- package/dist/source/session_context.js +265 -265
- package/dist/source/set_namespace_meta_data.d.ts +2 -2
- package/dist/source/set_namespace_meta_data.js +59 -59
- package/dist/source/ua_root_folder.d.ts +9 -9
- package/dist/source/ua_root_folder.js +2 -2
- package/dist/source/ua_two_state_variable_ex.d.ts +23 -23
- package/dist/source/ua_two_state_variable_ex.js +2 -2
- package/dist/source/xml_writer.d.ts +9 -9
- package/dist/source/xml_writer.js +2 -2
- package/dist/src/address_space.d.ts +392 -392
- package/dist/src/address_space.js +1392 -1392
- package/dist/src/address_space_change_event_tools.d.ts +6 -6
- package/dist/src/address_space_change_event_tools.js +149 -149
- package/dist/src/address_space_private.d.ts +43 -43
- package/dist/src/address_space_private.js +2 -2
- package/dist/src/alarms_and_conditions/check_where_clause.d.ts +4 -0
- package/dist/src/alarms_and_conditions/check_where_clause.js +110 -0
- package/dist/src/alarms_and_conditions/check_where_clause.js.map +1 -0
- package/dist/src/alarms_and_conditions/condition.d.ts +5 -5
- package/dist/src/alarms_and_conditions/condition.js +78 -78
- package/dist/src/alarms_and_conditions/condition_info.d.ts +27 -0
- package/dist/src/alarms_and_conditions/condition_info.js +55 -0
- package/dist/src/alarms_and_conditions/condition_info.js.map +1 -0
- package/dist/src/alarms_and_conditions/condition_info_impl.d.ts +26 -26
- package/dist/src/alarms_and_conditions/condition_info_impl.js +54 -54
- package/dist/src/alarms_and_conditions/condition_snapshot.d.ts +233 -0
- package/dist/src/alarms_and_conditions/condition_snapshot.js +667 -0
- package/dist/src/alarms_and_conditions/condition_snapshot.js.map +1 -0
- package/dist/src/alarms_and_conditions/condition_snapshot_impl.d.ts +222 -222
- package/dist/src/alarms_and_conditions/condition_snapshot_impl.js +657 -657
- package/dist/src/alarms_and_conditions/deviation_alarm_helper.d.ts +9 -9
- package/dist/src/alarms_and_conditions/deviation_alarm_helper.js +61 -61
- package/dist/src/alarms_and_conditions/extract_event_fields.d.ts +10 -0
- package/dist/src/alarms_and_conditions/extract_event_fields.js +90 -0
- package/dist/src/alarms_and_conditions/extract_event_fields.js.map +1 -0
- package/dist/src/alarms_and_conditions/index.d.ts +16 -16
- package/dist/src/alarms_and_conditions/index.js +32 -32
- package/dist/src/alarms_and_conditions/ua_acknowledgeable_condition_impl.d.ts +44 -44
- package/dist/src/alarms_and_conditions/ua_acknowledgeable_condition_impl.js +244 -244
- package/dist/src/alarms_and_conditions/ua_alarm_condition_impl.d.ts +93 -93
- package/dist/src/alarms_and_conditions/ua_alarm_condition_impl.js +419 -419
- package/dist/src/alarms_and_conditions/ua_base_event_impl.d.ts +26 -26
- package/dist/src/alarms_and_conditions/ua_base_event_impl.js +38 -38
- package/dist/src/alarms_and_conditions/ua_certificate_expiration_alarm_impl.d.ts +44 -44
- package/dist/src/alarms_and_conditions/ua_certificate_expiration_alarm_impl.js +183 -183
- package/dist/src/alarms_and_conditions/ua_condition_impl.d.ts +153 -153
- package/dist/src/alarms_and_conditions/ua_condition_impl.js +1028 -1028
- package/dist/src/alarms_and_conditions/ua_discrete_alarm_impl.d.ts +14 -14
- package/dist/src/alarms_and_conditions/ua_discrete_alarm_impl.js +34 -34
- package/dist/src/alarms_and_conditions/ua_exclusive_deviation_alarm_impl.d.ts +24 -24
- package/dist/src/alarms_and_conditions/ua_exclusive_deviation_alarm_impl.js +56 -56
- package/dist/src/alarms_and_conditions/ua_exclusive_level_alarm_impl.d.ts +11 -11
- package/dist/src/alarms_and_conditions/ua_exclusive_level_alarm_impl.js +11 -11
- package/dist/src/alarms_and_conditions/ua_exclusive_limit_alarm_impl.d.ts +23 -23
- package/dist/src/alarms_and_conditions/ua_exclusive_limit_alarm_impl.js +86 -86
- package/dist/src/alarms_and_conditions/ua_exclusive_rate_of_change_alarm_impl.d.ts +11 -11
- package/dist/src/alarms_and_conditions/ua_exclusive_rate_of_change_alarm_impl.js +7 -7
- package/dist/src/alarms_and_conditions/ua_limit_alarm_impl.d.ts +79 -79
- package/dist/src/alarms_and_conditions/ua_limit_alarm_impl.js +250 -250
- package/dist/src/alarms_and_conditions/ua_non_exclusive_deviation_alarm_impl.d.ts +24 -24
- package/dist/src/alarms_and_conditions/ua_non_exclusive_deviation_alarm_impl.js +50 -50
- package/dist/src/alarms_and_conditions/ua_non_exclusive_limit_alarm_impl.d.ts +19 -19
- package/dist/src/alarms_and_conditions/ua_non_exclusive_limit_alarm_impl.js +162 -162
- package/dist/src/alarms_and_conditions/ua_off_normal_alarm_impl.d.ts +46 -46
- package/dist/src/alarms_and_conditions/ua_off_normal_alarm_impl.js +166 -166
- package/dist/src/alarms_and_conditions/ua_system_off_normal_alarm_impl.d.ts +18 -18
- package/dist/src/alarms_and_conditions/ua_system_off_normal_alarm_impl.js +17 -17
- package/dist/src/apply_condition_refresh.d.ts +6 -6
- package/dist/src/apply_condition_refresh.js +27 -27
- package/dist/src/base_node_impl.d.ts +281 -281
- package/dist/src/base_node_impl.js +1395 -1395
- package/dist/src/base_node_private.d.ts +61 -61
- package/dist/src/base_node_private.js +705 -705
- package/dist/src/data_access/add_dataItem_stuff.d.ts +11 -11
- package/dist/src/data_access/add_dataItem_stuff.js +61 -61
- package/dist/src/data_access/check_variant_compatibility_ua_analog_item.d.ts +1 -1
- package/dist/src/data_access/check_variant_compatibility_ua_analog_item.js +34 -34
- package/dist/src/data_access/ua_multistate_discrete_impl.d.ts +32 -32
- package/dist/src/data_access/ua_multistate_discrete_impl.js +130 -130
- package/dist/src/data_access/ua_multistate_value_discrete.d.ts +51 -0
- package/dist/src/data_access/ua_multistate_value_discrete.js +250 -0
- package/dist/src/data_access/ua_multistate_value_discrete.js.map +1 -0
- package/dist/src/data_access/ua_multistate_value_discrete_impl.d.ts +51 -51
- package/dist/src/data_access/ua_multistate_value_discrete_impl.js +249 -249
- package/dist/src/data_access/ua_two_state_discrete.d.ts +25 -0
- package/dist/src/data_access/ua_two_state_discrete.js +154 -0
- package/dist/src/data_access/ua_two_state_discrete.js.map +1 -0
- package/dist/src/data_access/ua_two_state_discrete_impl.d.ts +25 -25
- package/dist/src/data_access/ua_two_state_discrete_impl.js +153 -153
- package/dist/src/event_data.d.ts +34 -34
- package/dist/src/event_data.js +64 -64
- package/dist/src/extension_object_array_node.d.ts +61 -61
- package/dist/src/extension_object_array_node.js +276 -276
- package/dist/src/historical_access/address_space_historical_data_node.d.ts +26 -26
- package/dist/src/historical_access/address_space_historical_data_node.js +630 -630
- package/dist/src/index_current.d.ts +43 -43
- package/dist/src/index_current.js +74 -74
- package/dist/src/namespace_impl.d.ts +461 -461
- package/dist/src/namespace_impl.js +1732 -1732
- package/dist/src/namespace_private.d.ts +21 -21
- package/dist/src/namespace_private.js +32 -32
- package/dist/src/nodeid_manager.d.ts +36 -36
- package/dist/src/nodeid_manager.js +197 -197
- package/dist/src/nodeset_tools/adjust_namespace_array.d.ts +2 -2
- package/dist/src/nodeset_tools/adjust_namespace_array.js +13 -13
- package/dist/src/nodeset_tools/construct_namespace_dependency.d.ts +2 -2
- package/dist/src/nodeset_tools/construct_namespace_dependency.js +83 -83
- package/dist/src/nodeset_tools/nodeset_to_xml.d.ts +2 -2
- package/dist/src/nodeset_tools/nodeset_to_xml.js +1155 -1155
- package/dist/src/nodeset_tools/typedictionary_to_xml.d.ts +2 -2
- package/dist/src/nodeset_tools/typedictionary_to_xml.js +154 -154
- package/dist/src/reference_impl.d.ts +43 -43
- package/dist/src/reference_impl.js +139 -139
- package/dist/src/role_permissions.d.ts +2 -2
- package/dist/src/role_permissions.js +10 -10
- package/dist/src/state_machine/finite_state_machine.d.ts +67 -67
- package/dist/src/state_machine/finite_state_machine.js +353 -353
- package/dist/src/state_machine/ua_shelving_state_machine_ex.d.ts +38 -38
- package/dist/src/state_machine/ua_shelving_state_machine_ex.js +250 -250
- package/dist/src/state_machine/ua_two_state_variable.d.ts +61 -61
- package/dist/src/state_machine/ua_two_state_variable.js +331 -331
- package/dist/src/tool_isSupertypeOf.d.ts +17 -17
- package/dist/src/tool_isSupertypeOf.js +108 -108
- package/dist/src/ua_condition_type.d.ts +8 -8
- package/dist/src/ua_condition_type.js +2 -2
- package/dist/src/ua_data_type_impl.d.ts +93 -93
- package/dist/src/ua_data_type_impl.js +371 -371
- package/dist/src/ua_method_impl.d.ts +41 -41
- package/dist/src/ua_method_impl.js +208 -208
- package/dist/src/ua_object_impl.d.ts +35 -35
- package/dist/src/ua_object_impl.js +161 -161
- package/dist/src/ua_object_type_impl.d.ts +48 -48
- package/dist/src/ua_object_type_impl.js +124 -124
- package/dist/src/ua_reference_type_impl.d.ts +43 -43
- package/dist/src/ua_reference_type_impl.js +139 -139
- package/dist/src/ua_variable_impl.d.ts +351 -351
- package/dist/src/ua_variable_impl.js +1604 -1604
- package/dist/src/ua_variable_impl_ext_obj.d.ts +17 -17
- package/dist/src/ua_variable_impl_ext_obj.js +437 -437
- package/dist/src/ua_variable_type_impl.d.ts +62 -62
- package/dist/src/ua_variable_type_impl.js +570 -570
- package/dist/src/ua_view_impl.d.ts +19 -19
- package/dist/src/ua_view_impl.js +43 -43
- package/distHelpers/add_event_generator_object.d.ts +3 -3
- package/distHelpers/add_event_generator_object.js +64 -64
- package/distHelpers/alarms_and_conditions_demo.d.ts +9 -9
- package/distHelpers/alarms_and_conditions_demo.js +115 -115
- package/distHelpers/assertHasMatchingReference.d.ts +19 -19
- package/distHelpers/assertHasMatchingReference.js +40 -40
- package/distHelpers/boiler_system.d.ts +113 -113
- package/distHelpers/boiler_system.js +395 -395
- package/distHelpers/create_minimalist_address_space_nodeset.d.ts +5 -5
- package/distHelpers/create_minimalist_address_space_nodeset.js +171 -171
- package/distHelpers/date_utils.d.ts +3 -3
- package/distHelpers/date_utils.js +9 -9
- package/distHelpers/dump_statemachine.js +127 -127
- package/distHelpers/get_address_space_fixture.d.ts +1 -1
- package/distHelpers/get_address_space_fixture.js +30 -30
- package/distHelpers/get_mini_address_space.d.ts +7 -7
- package/distHelpers/get_mini_address_space.js +36 -36
- package/distHelpers/index.d.ts +12 -12
- package/distHelpers/index.js +28 -28
- package/distHelpers/mock_session.d.ts +14 -14
- package/distHelpers/mock_session.js +25 -25
- package/distNodeJS/generate_address_space.d.ts +4 -4
- package/distNodeJS/generate_address_space.js +41 -41
- package/distNodeJS/index.d.ts +1 -1
- package/distNodeJS/index.js +17 -17
- package/package.json +36 -35
|
@@ -1,1029 +1,1029 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.UAConditionImpl = void 0;
|
|
4
|
-
/* eslint-disable complexity */
|
|
5
|
-
/**
|
|
6
|
-
* @module node-opcua-address-space.AlarmsAndConditions
|
|
7
|
-
*/
|
|
8
|
-
const chalk = require("chalk");
|
|
9
|
-
const node_opcua_assert_1 = require("node-opcua-assert");
|
|
10
|
-
const node_opcua_basic_types_1 = require("node-opcua-basic-types");
|
|
11
|
-
const node_opcua_data_model_1 = require("node-opcua-data-model");
|
|
12
|
-
const node_opcua_debug_1 = require("node-opcua-debug");
|
|
13
|
-
const node_opcua_basic_types_2 = require("node-opcua-basic-types");
|
|
14
|
-
const node_opcua_nodeid_1 = require("node-opcua-nodeid");
|
|
15
|
-
const node_opcua_status_code_1 = require("node-opcua-status-code");
|
|
16
|
-
const node_opcua_types_1 = require("node-opcua-types");
|
|
17
|
-
const node_opcua_variant_1 = require("node-opcua-variant");
|
|
18
|
-
const ua_two_state_variable_1 = require("../state_machine/ua_two_state_variable");
|
|
19
|
-
const ua_object_impl_1 = require("../ua_object_impl");
|
|
20
|
-
const ua_base_event_impl_1 = require("./ua_base_event_impl");
|
|
21
|
-
const condition_snapshot_impl_1 = require("./condition_snapshot_impl");
|
|
22
|
-
const debugLog = (0, node_opcua_debug_1.make_debugLog)(__filename);
|
|
23
|
-
const errorLog = (0, node_opcua_debug_1.make_errorLog)(__filename);
|
|
24
|
-
const doDebug = (0, node_opcua_debug_1.checkDebugFlag)(__filename);
|
|
25
|
-
const warningLog = (0, node_opcua_debug_1.make_warningLog)(__filename);
|
|
26
|
-
/**
|
|
27
|
-
*
|
|
28
|
-
* └─ ConditionType
|
|
29
|
-
* ├─ DialogConditionType
|
|
30
|
-
* └─ AcknowledgeableConditionType
|
|
31
|
-
* └─ AlarmConditionType
|
|
32
|
-
* ├─ LimitAlarmType
|
|
33
|
-
* │ ├─ ExclusiveLimitAlarmType
|
|
34
|
-
* │ │ ├─ ExclusiveLevelAlarmType
|
|
35
|
-
* │ │ ├─ ExclusiveDeviationAlarmType
|
|
36
|
-
* │ │ └─ ExclusiveRateOfChangeAlarmType
|
|
37
|
-
* │ └─ NonExclusiveLimitAlarmType
|
|
38
|
-
* │ ├─ NonExclusiveLevelAlarmType
|
|
39
|
-
* │ ├─ NonExclusiveDeviationAlarmType
|
|
40
|
-
* │ └─ NonExclusiveRateOfChangeAlarmType
|
|
41
|
-
* └─ DiscreteAlarmType
|
|
42
|
-
* ├─ OffNormalAlarmType
|
|
43
|
-
* │ ├─ SystemOffNormalAlarmType
|
|
44
|
-
* │ │ └─ CertificateExpirationAlarmType
|
|
45
|
-
* │ └─ TripAlarmType
|
|
46
|
-
*
|
|
47
|
-
*/
|
|
48
|
-
class UAConditionImpl extends ua_base_event_impl_1.UABaseEventImpl {
|
|
49
|
-
constructor() {
|
|
50
|
-
super(...arguments);
|
|
51
|
-
this._branch0 = null;
|
|
52
|
-
this._previousRetainFlag = false;
|
|
53
|
-
this._branches = {};
|
|
54
|
-
}
|
|
55
|
-
static instantiate(namespace, conditionTypeId, options, data) {
|
|
56
|
-
return UACondition_instantiate(namespace, conditionTypeId, options, data);
|
|
57
|
-
}
|
|
58
|
-
static install_condition_refresh_handle(addressSpace) {
|
|
59
|
-
//
|
|
60
|
-
// install ConditionRefresh
|
|
61
|
-
//
|
|
62
|
-
// NOTE:
|
|
63
|
-
// OPCUA doesn't implement the condition refresh method ! yet
|
|
64
|
-
// .5.7 ConditionRefresh Method
|
|
65
|
-
// ConditionRefresh allows a Client to request a Refresh of all Condition instances that currently
|
|
66
|
-
// are in an interesting state (they have the Retain flag set). This includes previous states of a
|
|
67
|
-
// Condition instance for which the Server maintains Branches. A Client would typically invoke
|
|
68
|
-
// this Method when it initially connects to a Server and following any situations, such as
|
|
69
|
-
// communication disruptions, in which it would require resynchronization with the Server. This
|
|
70
|
-
// Method is only available on the ConditionType or its subtypes. To invoke this Method, the call
|
|
71
|
-
// shall pass the well known MethodId of the Method on the ConditionType and the ObjectId
|
|
72
|
-
// shall be the well known ObjectId of the ConditionType Object.
|
|
73
|
-
const conditionType = addressSpace.findEventType("ConditionType");
|
|
74
|
-
(0, node_opcua_assert_1.assert)(conditionType !== null);
|
|
75
|
-
conditionType.disable.bindMethod(_disable_method);
|
|
76
|
-
conditionType.enable.bindMethod(_enable_method);
|
|
77
|
-
conditionType.conditionRefresh.bindMethod(_condition_refresh_method);
|
|
78
|
-
conditionType.conditionRefresh2.bindMethod(_condition_refresh2_method);
|
|
79
|
-
// those methods can be call on the ConditionType or on the ConditionInstance itself...
|
|
80
|
-
conditionType.addComment.bindMethod(_add_comment_method);
|
|
81
|
-
}
|
|
82
|
-
/**
|
|
83
|
-
*
|
|
84
|
-
* Helper method to handle condition methods that takes a branchId and a comment
|
|
85
|
-
*
|
|
86
|
-
*/
|
|
87
|
-
static with_condition_method(inputArguments, context, callback, inner_func) {
|
|
88
|
-
const conditionNode = context.object;
|
|
89
|
-
// xx console.log(inputArguments.map(function(a){return a.toString()}));
|
|
90
|
-
if (!(conditionNode instanceof UAConditionImpl)) {
|
|
91
|
-
callback(null, {
|
|
92
|
-
statusCode: node_opcua_status_code_1.StatusCodes.BadNodeIdInvalid
|
|
93
|
-
});
|
|
94
|
-
return;
|
|
95
|
-
}
|
|
96
|
-
if (!conditionNode.getEnabledState()) {
|
|
97
|
-
callback(null, {
|
|
98
|
-
statusCode: node_opcua_status_code_1.StatusCodes.BadConditionDisabled
|
|
99
|
-
});
|
|
100
|
-
return;
|
|
101
|
-
}
|
|
102
|
-
// inputArguments has 2 arguments
|
|
103
|
-
// EventId => ByteString The Identifier of the event to comment
|
|
104
|
-
// Comment => LocalizedText The Comment to add to the condition
|
|
105
|
-
(0, node_opcua_assert_1.assert)(inputArguments.length === 2);
|
|
106
|
-
(0, node_opcua_assert_1.assert)(inputArguments[0].dataType === node_opcua_variant_1.DataType.ByteString);
|
|
107
|
-
(0, node_opcua_assert_1.assert)(inputArguments[1].dataType === node_opcua_variant_1.DataType.LocalizedText);
|
|
108
|
-
const eventId = inputArguments[0].value;
|
|
109
|
-
(0, node_opcua_assert_1.assert)(!eventId || eventId instanceof Buffer);
|
|
110
|
-
const comment = inputArguments[1].value;
|
|
111
|
-
(0, node_opcua_assert_1.assert)(comment instanceof node_opcua_data_model_1.LocalizedText);
|
|
112
|
-
const branch = conditionNode._findBranchForEventId(eventId);
|
|
113
|
-
if (!branch) {
|
|
114
|
-
callback(null, {
|
|
115
|
-
statusCode: node_opcua_status_code_1.StatusCodes.BadEventIdUnknown
|
|
116
|
-
});
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
|
-
(0, node_opcua_assert_1.assert)(branch instanceof condition_snapshot_impl_1.ConditionSnapshotImpl);
|
|
120
|
-
const statusCode = inner_func(eventId, comment, branch, conditionNode);
|
|
121
|
-
// record also who did the call
|
|
122
|
-
branch.setClientUserId(context.userIdentity || "<unknown client user id>");
|
|
123
|
-
callback(null, {
|
|
124
|
-
statusCode
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
/**
|
|
128
|
-
* @method initialize
|
|
129
|
-
* @private
|
|
130
|
-
*/
|
|
131
|
-
initialize() {
|
|
132
|
-
this._branches = {};
|
|
133
|
-
}
|
|
134
|
-
/**
|
|
135
|
-
* @method post_initialize
|
|
136
|
-
* @private
|
|
137
|
-
*/
|
|
138
|
-
post_initialize() {
|
|
139
|
-
(0, node_opcua_assert_1.assert)(!this._branch0);
|
|
140
|
-
this._branch0 = new condition_snapshot_impl_1.ConditionSnapshotImpl(this, new node_opcua_nodeid_1.NodeId());
|
|
141
|
-
// the condition OPCUA object alway reflects the default branch states
|
|
142
|
-
// so we set a mechanism that automatically keeps self in sync
|
|
143
|
-
// with the default branch.
|
|
144
|
-
// the implication of this convention is that interacting with the condition variable
|
|
145
|
-
// shall be made by using branch0, any value change made
|
|
146
|
-
// using the standard setValueFromSource mechanism will not be work properly.
|
|
147
|
-
this._branch0.on("value_changed", (node, variant) => {
|
|
148
|
-
(0, node_opcua_assert_1.assert)(node.nodeClass === node_opcua_data_model_1.NodeClass.Variable);
|
|
149
|
-
node.setValueFromSource(variant);
|
|
150
|
-
});
|
|
151
|
-
}
|
|
152
|
-
getBranchCount() {
|
|
153
|
-
return Object.keys(this._branches).length;
|
|
154
|
-
}
|
|
155
|
-
getBranches() {
|
|
156
|
-
return Object.keys(this._branches).map((x) => {
|
|
157
|
-
return this._branches[x];
|
|
158
|
-
});
|
|
159
|
-
}
|
|
160
|
-
getBranchIds() {
|
|
161
|
-
return this.getBranches().map((b) => b.getBranchId());
|
|
162
|
-
}
|
|
163
|
-
/**
|
|
164
|
-
* @method createBranch
|
|
165
|
-
* @return {ConditionSnapshot}
|
|
166
|
-
*/
|
|
167
|
-
createBranch() {
|
|
168
|
-
const branchId = _create_new_branch_id();
|
|
169
|
-
const snapshot = new condition_snapshot_impl_1.ConditionSnapshotImpl(this, branchId);
|
|
170
|
-
this._branches[branchId.toString()] = snapshot;
|
|
171
|
-
return snapshot;
|
|
172
|
-
}
|
|
173
|
-
/**
|
|
174
|
-
* @method deleteBranch
|
|
175
|
-
* @param branch {ConditionSnapshot}
|
|
176
|
-
*/
|
|
177
|
-
deleteBranch(branch) {
|
|
178
|
-
const key = branch.getBranchId().toString();
|
|
179
|
-
(0, node_opcua_assert_1.assert)(!(0, node_opcua_nodeid_1.sameNodeId)(branch.getBranchId(), node_opcua_nodeid_1.NodeId.nullNodeId), "cannot delete branch zero");
|
|
180
|
-
(0, node_opcua_assert_1.assert)(Object.prototype.hasOwnProperty.call(this._branches, key));
|
|
181
|
-
delete this._branches[key];
|
|
182
|
-
this.emit("branch_deleted", key);
|
|
183
|
-
}
|
|
184
|
-
/**
|
|
185
|
-
* @method getEnabledState
|
|
186
|
-
* @return {Boolean}
|
|
187
|
-
*/
|
|
188
|
-
getEnabledState() {
|
|
189
|
-
return this.enabledState.getValue();
|
|
190
|
-
}
|
|
191
|
-
/**
|
|
192
|
-
* @method getEnabledStateAsString
|
|
193
|
-
* @return {String}
|
|
194
|
-
*/
|
|
195
|
-
getEnabledStateAsString() {
|
|
196
|
-
return this.enabledState.getValueAsString();
|
|
197
|
-
}
|
|
198
|
-
/**
|
|
199
|
-
* returns {StatusCode} StatusCodes.Good if successful or BadConditionAlreadyEnabled/BadConditionAlreadyDisabled
|
|
200
|
-
* @private
|
|
201
|
-
*/
|
|
202
|
-
_setEnabledState(requestedEnabledState) {
|
|
203
|
-
(0, node_opcua_assert_1.assert)(typeof requestedEnabledState === "boolean");
|
|
204
|
-
const enabledState = this.getEnabledState();
|
|
205
|
-
if (enabledState && requestedEnabledState) {
|
|
206
|
-
return node_opcua_status_code_1.StatusCodes.BadConditionAlreadyEnabled;
|
|
207
|
-
}
|
|
208
|
-
if (!enabledState && !requestedEnabledState) {
|
|
209
|
-
return node_opcua_status_code_1.StatusCodes.BadConditionAlreadyDisabled;
|
|
210
|
-
}
|
|
211
|
-
this._branch0.setEnabledState(requestedEnabledState);
|
|
212
|
-
// conditionNode.enabledState.setValue(requestedEnabledState);
|
|
213
|
-
// xx assert(conditionNode.enabledState.id.readValue().value.value === requestedEnabledState,"sanity check 1");
|
|
214
|
-
// xx assert(conditionNode.currentBranch().getEnabledState() === requestedEnabledState,"sanity check 2");
|
|
215
|
-
if (!requestedEnabledState) {
|
|
216
|
-
// as per Spec 1.0.3 part 9:
|
|
217
|
-
// * When the Condition instance enters the Disabled state, the Retain Property of this
|
|
218
|
-
// Condition shall be set to FALSE by the Server to indicate to the Client that the
|
|
219
|
-
// Condition instance is currently not of interest to Clients.
|
|
220
|
-
// TODO : shall we really set retain to false or artificially expose the retain false as false
|
|
221
|
-
// whist enabled state is false ?
|
|
222
|
-
this._previousRetainFlag = this.currentBranch().getRetain();
|
|
223
|
-
this.currentBranch().setRetain(false);
|
|
224
|
-
// todo: install the mechanism by which all condition values will be return
|
|
225
|
-
// as Null | BadConditionDisabled;
|
|
226
|
-
const statusCode = node_opcua_status_code_1.StatusCodes.BadConditionDisabled;
|
|
227
|
-
// a notification must be send
|
|
228
|
-
this.raiseConditionEvent(this.currentBranch(), true);
|
|
229
|
-
}
|
|
230
|
-
else {
|
|
231
|
-
// * When the Condition instance enters the enabled state, the Condition shall be
|
|
232
|
-
// evaluated and all of its Properties updated to reflect the current values. If this
|
|
233
|
-
// evaluation causes the Retain Property to transition to TRUE for any ConditionBranch,
|
|
234
|
-
// then an Event Notification shall be generated for that ConditionBranch.
|
|
235
|
-
this.evaluateConditionsAfterEnabled();
|
|
236
|
-
// todo evaluate branches
|
|
237
|
-
// conditionNode.evaluateBranches();
|
|
238
|
-
// restore retain flag
|
|
239
|
-
if (Object.prototype.hasOwnProperty.call(this, "_previousRetainFlag")) {
|
|
240
|
-
this.currentBranch().setRetain(this._previousRetainFlag);
|
|
241
|
-
}
|
|
242
|
-
// todo send notification for branches with retain = true
|
|
243
|
-
let nb_condition_resent = 0;
|
|
244
|
-
if (this.currentBranch().getRetain()) {
|
|
245
|
-
nb_condition_resent += this._resend_conditionEvents();
|
|
246
|
-
}
|
|
247
|
-
if (nb_condition_resent === 0) {
|
|
248
|
-
// a notification must be send
|
|
249
|
-
this.raiseConditionEvent(this.currentBranch(), true);
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
return node_opcua_status_code_1.StatusCodes.Good;
|
|
253
|
-
}
|
|
254
|
-
/**
|
|
255
|
-
*
|
|
256
|
-
* @method setEnabledState
|
|
257
|
-
* @param requestedEnabledState {Boolean}
|
|
258
|
-
* @private
|
|
259
|
-
*/
|
|
260
|
-
setEnabledState(requestedEnabledState) {
|
|
261
|
-
return this._setEnabledState(requestedEnabledState);
|
|
262
|
-
}
|
|
263
|
-
/**
|
|
264
|
-
* @method setReceiveTime
|
|
265
|
-
* @param time {Date}
|
|
266
|
-
*/
|
|
267
|
-
setReceiveTime(time) {
|
|
268
|
-
return this._branch0.setReceiveTime(time);
|
|
269
|
-
}
|
|
270
|
-
/**
|
|
271
|
-
* @method setLocalTime (optional)
|
|
272
|
-
* @param time
|
|
273
|
-
*/
|
|
274
|
-
setLocalTime(time) {
|
|
275
|
-
return this._branch0.setLocalTime(time);
|
|
276
|
-
}
|
|
277
|
-
/**
|
|
278
|
-
* @method setTime
|
|
279
|
-
* @param time {Date}
|
|
280
|
-
*/
|
|
281
|
-
setTime(time) {
|
|
282
|
-
return this._branch0.setTime(time);
|
|
283
|
-
}
|
|
284
|
-
_assert_valid() {
|
|
285
|
-
(0, node_opcua_assert_1.assert)(this.receiveTime.readValue().value.dataType === node_opcua_variant_1.DataType.DateTime);
|
|
286
|
-
(0, node_opcua_assert_1.assert)(this.receiveTime.readValue().value.value instanceof Date);
|
|
287
|
-
(0, node_opcua_assert_1.assert)(this.message.readValue().value.dataType === node_opcua_variant_1.DataType.LocalizedText);
|
|
288
|
-
(0, node_opcua_assert_1.assert)(this.severity.readValue().value.dataType === node_opcua_variant_1.DataType.UInt16);
|
|
289
|
-
(0, node_opcua_assert_1.assert)(this.time.readValue().value.dataType === node_opcua_variant_1.DataType.DateTime);
|
|
290
|
-
(0, node_opcua_assert_1.assert)(this.time.readValue().value.value instanceof Date);
|
|
291
|
-
(0, node_opcua_assert_1.assert)(this.quality.readValue().value.dataType === node_opcua_variant_1.DataType.StatusCode);
|
|
292
|
-
(0, node_opcua_assert_1.assert)(this.enabledState.readValue().value.dataType === node_opcua_variant_1.DataType.LocalizedText);
|
|
293
|
-
(0, node_opcua_assert_1.assert)(this.branchId.readValue().value.dataType === node_opcua_variant_1.DataType.NodeId);
|
|
294
|
-
// note localTime has been made optional in 1.04
|
|
295
|
-
(0, node_opcua_assert_1.assert)(!this.localTime || this.localTime.readValue().value.dataType === node_opcua_variant_1.DataType.ExtensionObject);
|
|
296
|
-
}
|
|
297
|
-
/**
|
|
298
|
-
* @method conditionOfNode
|
|
299
|
-
* @return {UAObject}
|
|
300
|
-
*/
|
|
301
|
-
conditionOfNode() {
|
|
302
|
-
const refs = this.findReferencesExAsObject("HasCondition", node_opcua_data_model_1.BrowseDirection.Inverse);
|
|
303
|
-
if (refs.length === 0) {
|
|
304
|
-
return null;
|
|
305
|
-
}
|
|
306
|
-
(0, node_opcua_assert_1.assert)(refs.length !== 0, "UACondition must be the condition of some node");
|
|
307
|
-
(0, node_opcua_assert_1.assert)(refs.length === 1, "expecting only one ConditionOf");
|
|
308
|
-
const node = refs[0];
|
|
309
|
-
(0, node_opcua_assert_1.assert)(node.nodeClass === node_opcua_data_model_1.NodeClass.Object || node.nodeClass === node_opcua_data_model_1.NodeClass.Variable, "node for which we are the condition shall be an UAObject or UAVariable");
|
|
310
|
-
return node;
|
|
311
|
-
}
|
|
312
|
-
/**
|
|
313
|
-
* @method raiseConditionEvent
|
|
314
|
-
* Raise a Instance Event
|
|
315
|
-
* (see also UAObject#raiseEvent to raise a transient event)
|
|
316
|
-
* @param branch the condition branch to raise
|
|
317
|
-
* @param renewEventId true if event Id of the condition branch should be renewed
|
|
318
|
-
*/
|
|
319
|
-
raiseConditionEvent(branch, renewEventId) {
|
|
320
|
-
(0, node_opcua_assert_1.assert)(arguments.length === 2, "expecting 2 arguments");
|
|
321
|
-
if (renewEventId) {
|
|
322
|
-
branch.renewEventId();
|
|
323
|
-
}
|
|
324
|
-
// xx console.log("MMMMMMMM%%%%%%%%%%%%%%%%%%%%% branch " +
|
|
325
|
-
// branch.getBranchId().toString() + " eventId = " + branch.getEventId().toString("hex"));
|
|
326
|
-
(0, node_opcua_assert_1.assert)(branch instanceof condition_snapshot_impl_1.ConditionSnapshotImpl);
|
|
327
|
-
this._assert_valid();
|
|
328
|
-
// In fact the event is raised by the object of which we are the condition
|
|
329
|
-
const conditionOfNode = this.conditionOfNode();
|
|
330
|
-
if (conditionOfNode) {
|
|
331
|
-
const eventData = branch._constructEventData();
|
|
332
|
-
this.emit("event", eventData);
|
|
333
|
-
if (conditionOfNode instanceof ua_object_impl_1.UAObjectImpl) {
|
|
334
|
-
// xx assert(conditionOfNode.eventNotifier === 0x01);
|
|
335
|
-
conditionOfNode._bubble_up_event(eventData);
|
|
336
|
-
}
|
|
337
|
-
else {
|
|
338
|
-
(0, node_opcua_assert_1.assert)(conditionOfNode.nodeClass === node_opcua_data_model_1.NodeClass.Variable);
|
|
339
|
-
// in this case
|
|
340
|
-
const eventOfs = conditionOfNode.getEventSourceOfs();
|
|
341
|
-
(0, node_opcua_assert_1.assert)(eventOfs.length === 1);
|
|
342
|
-
const node = eventOfs[0];
|
|
343
|
-
if (node instanceof ua_object_impl_1.UAObjectImpl) {
|
|
344
|
-
node._bubble_up_event(eventData);
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
else {
|
|
349
|
-
warningLog("Condition ", this.nodeId.toString(), "is not linked to a Object with a IsConditionOf(reversed(HasCondition))");
|
|
350
|
-
}
|
|
351
|
-
// xx console.log("MMMMMMMM%%%%%%%%%%%%%%%%%%%%% branch " +
|
|
352
|
-
// branch.getBranchId().toString() + " eventId = " + branch.getEventId().toString("hex"));
|
|
353
|
-
}
|
|
354
|
-
/**
|
|
355
|
-
*
|
|
356
|
-
* @method raiseNewCondition
|
|
357
|
-
* @param conditionInfo {ConditionInfo}
|
|
358
|
-
*
|
|
359
|
-
*/
|
|
360
|
-
raiseNewCondition(conditionInfo) {
|
|
361
|
-
if (!this.getEnabledState()) {
|
|
362
|
-
throw new Error("UACondition#raiseNewCondition Condition is not enabled");
|
|
363
|
-
}
|
|
364
|
-
conditionInfo = conditionInfo || {};
|
|
365
|
-
conditionInfo.severity = Object.prototype.hasOwnProperty.call(conditionInfo, "severity")
|
|
366
|
-
? conditionInfo.severity
|
|
367
|
-
: UAConditionImpl.defaultSeverity;
|
|
368
|
-
// only valid for ConditionObjects
|
|
369
|
-
// todo check that object is of type ConditionType
|
|
370
|
-
const addressSpace = this.addressSpace;
|
|
371
|
-
const selfConditionType = this.typeDefinitionObj;
|
|
372
|
-
const conditionType = addressSpace.findObjectType("ConditionType");
|
|
373
|
-
(0, node_opcua_assert_1.assert)(selfConditionType.isSupertypeOf(conditionType));
|
|
374
|
-
const branch = this.currentBranch();
|
|
375
|
-
const now = new Date();
|
|
376
|
-
// install the eventTimestamp
|
|
377
|
-
// set the received Time
|
|
378
|
-
branch.setTime(now);
|
|
379
|
-
branch.setReceiveTime(now);
|
|
380
|
-
// note : in 1.04 LocalTime property is optional
|
|
381
|
-
if (Object.prototype.hasOwnProperty.call(this, "localTime")) {
|
|
382
|
-
branch.setLocalTime(new node_opcua_types_1.TimeZoneDataType({
|
|
383
|
-
daylightSavingInOffset: false,
|
|
384
|
-
offset: 0
|
|
385
|
-
}));
|
|
386
|
-
}
|
|
387
|
-
if (Object.prototype.hasOwnProperty.call(conditionInfo, "message") && conditionInfo.message) {
|
|
388
|
-
branch.setMessage(conditionInfo.message);
|
|
389
|
-
}
|
|
390
|
-
// todo receive time : when the server received the event from the underlying system.
|
|
391
|
-
// self.receiveTime.setValueFromSource();
|
|
392
|
-
if (Object.prototype.hasOwnProperty.call(conditionInfo, "severity") && conditionInfo.severity !== null) {
|
|
393
|
-
(0, node_opcua_assert_1.assert)(isFinite(conditionInfo.severity));
|
|
394
|
-
branch.setSeverity(conditionInfo.severity);
|
|
395
|
-
}
|
|
396
|
-
if (Object.prototype.hasOwnProperty.call(conditionInfo, "quality") && conditionInfo.quality !== null) {
|
|
397
|
-
(0, node_opcua_assert_1.assert)(conditionInfo.quality instanceof node_opcua_status_code_1.StatusCode);
|
|
398
|
-
branch.setQuality(conditionInfo.quality);
|
|
399
|
-
}
|
|
400
|
-
if (Object.prototype.hasOwnProperty.call(conditionInfo, "retain") && conditionInfo.retain !== null) {
|
|
401
|
-
(0, node_opcua_assert_1.assert)(typeof conditionInfo.retain === "boolean");
|
|
402
|
-
branch.setRetain(!!conditionInfo.retain);
|
|
403
|
-
}
|
|
404
|
-
this.raiseConditionEvent(branch, true);
|
|
405
|
-
}
|
|
406
|
-
raiseNewBranchState(branch) {
|
|
407
|
-
this.raiseConditionEvent(branch, true);
|
|
408
|
-
if (!(0, node_opcua_nodeid_1.sameNodeId)(branch.getBranchId(), node_opcua_nodeid_1.NodeId.nullNodeId) && !branch.getRetain()) {
|
|
409
|
-
// xx console.log(" Deleting not longer needed branch ", branch.getBranchId().toString());
|
|
410
|
-
// branch can be deleted
|
|
411
|
-
this.deleteBranch(branch);
|
|
412
|
-
}
|
|
413
|
-
}
|
|
414
|
-
/**
|
|
415
|
-
* @method currentBranch
|
|
416
|
-
* @return {ConditionSnapshot}
|
|
417
|
-
*/
|
|
418
|
-
currentBranch() {
|
|
419
|
-
return this._branch0;
|
|
420
|
-
}
|
|
421
|
-
_resend_conditionEvents() {
|
|
422
|
-
// for the time being , only current branch
|
|
423
|
-
const currentBranch = this.currentBranch();
|
|
424
|
-
if (currentBranch.getRetain()) {
|
|
425
|
-
debugLog(" resending condition event for " + this.browseName.toString());
|
|
426
|
-
this.raiseConditionEvent(currentBranch, false);
|
|
427
|
-
return 1;
|
|
428
|
-
}
|
|
429
|
-
return 0;
|
|
430
|
-
}
|
|
431
|
-
// ------------------------------------------------------------------------------------
|
|
432
|
-
// Acknowledgeable
|
|
433
|
-
// ------------------------------------------------------------------------------------
|
|
434
|
-
/**
|
|
435
|
-
* @method _raiseAuditConditionCommentEvent
|
|
436
|
-
* @param sourceName {string}
|
|
437
|
-
* @param conditionEventId {Buffer}
|
|
438
|
-
* @param comment {LocalizedText}
|
|
439
|
-
* @private
|
|
440
|
-
*/
|
|
441
|
-
_raiseAuditConditionCommentEvent(sourceName, conditionEventId, comment) {
|
|
442
|
-
(0, node_opcua_assert_1.assert)(conditionEventId === null || conditionEventId instanceof Buffer);
|
|
443
|
-
(0, node_opcua_assert_1.assert)(comment instanceof node_opcua_data_model_1.LocalizedText);
|
|
444
|
-
const server = this.addressSpace.rootFolder.objects.server;
|
|
445
|
-
const now = new Date();
|
|
446
|
-
// xx if (true || server.isAuditing) {
|
|
447
|
-
// ----------------------------------------------------------------------------------------------------
|
|
448
|
-
server.raiseEvent("AuditConditionCommentEventType", {
|
|
449
|
-
// AuditEventType
|
|
450
|
-
/* part 5 - 6.4.3 AuditEventType */
|
|
451
|
-
actionTimeStamp: {
|
|
452
|
-
dataType: "DateTime",
|
|
453
|
-
value: now
|
|
454
|
-
},
|
|
455
|
-
status: {
|
|
456
|
-
dataType: "Boolean",
|
|
457
|
-
value: true
|
|
458
|
-
},
|
|
459
|
-
serverId: {
|
|
460
|
-
dataType: "String",
|
|
461
|
-
value: ""
|
|
462
|
-
},
|
|
463
|
-
// ClientAuditEntryId contains the human-readable AuditEntryId defined in Part 3.
|
|
464
|
-
clientAuditEntryId: {
|
|
465
|
-
dataType: "String",
|
|
466
|
-
value: ""
|
|
467
|
-
},
|
|
468
|
-
// The ClientUserId identifies the user of the client requesting an action. The ClientUserId can be
|
|
469
|
-
// obtained from the UserIdentityToken passed in the ActivateSession call.
|
|
470
|
-
clientUserId: {
|
|
471
|
-
dataType: "String",
|
|
472
|
-
value: ""
|
|
473
|
-
},
|
|
474
|
-
sourceName: {
|
|
475
|
-
dataType: "String",
|
|
476
|
-
value: sourceName
|
|
477
|
-
},
|
|
478
|
-
// AuditUpdateMethodEventType
|
|
479
|
-
methodId: {
|
|
480
|
-
dataType: "Null"
|
|
481
|
-
},
|
|
482
|
-
inputArguments: {
|
|
483
|
-
dataType: "Null"
|
|
484
|
-
},
|
|
485
|
-
// AuditConditionCommentEventType
|
|
486
|
-
conditionEventId: {
|
|
487
|
-
dataType: "ByteString",
|
|
488
|
-
value: conditionEventId
|
|
489
|
-
},
|
|
490
|
-
comment: {
|
|
491
|
-
dataType: "LocalizedText",
|
|
492
|
-
value: comment
|
|
493
|
-
}
|
|
494
|
-
});
|
|
495
|
-
// xx }
|
|
496
|
-
}
|
|
497
|
-
_findBranchForEventId(eventId) {
|
|
498
|
-
if (sameBuffer(this.eventId.readValue().value.value, eventId)) {
|
|
499
|
-
return this.currentBranch();
|
|
500
|
-
}
|
|
501
|
-
const e = Object.values(this._branches).filter((branch) => sameBuffer(branch.getEventId(), eventId));
|
|
502
|
-
if (e.length === 1) {
|
|
503
|
-
return e[0];
|
|
504
|
-
}
|
|
505
|
-
(0, node_opcua_assert_1.assert)(e.length === 0, "cannot have 2 branches with same eventId");
|
|
506
|
-
return null; // not found
|
|
507
|
-
}
|
|
508
|
-
evaluateConditionsAfterEnabled() {
|
|
509
|
-
(0, node_opcua_assert_1.assert)(this.getEnabledState() === true);
|
|
510
|
-
throw new Error("Unimplemented , please override");
|
|
511
|
-
}
|
|
512
|
-
}
|
|
513
|
-
exports.UAConditionImpl = UAConditionImpl;
|
|
514
|
-
UAConditionImpl.defaultSeverity = 250;
|
|
515
|
-
UAConditionImpl.typeDefinition = (0, node_opcua_nodeid_1.resolveNodeId)("ConditionType");
|
|
516
|
-
/**
|
|
517
|
-
* instantiate a Condition.
|
|
518
|
-
* this will create the unique EventId and will set eventType
|
|
519
|
-
* @method instantiate
|
|
520
|
-
* @param namespace {INamespace}
|
|
521
|
-
* @param conditionTypeId {String|NodeId} the EventType to instantiate
|
|
522
|
-
* @param options {object}
|
|
523
|
-
* @param options.browseName {String|QualifiedName}
|
|
524
|
-
* @param options.componentOf {NodeId|UAObject}
|
|
525
|
-
* @param options.conditionOf {NodeId|UAObject} Mandatory
|
|
526
|
-
* @param options.organizedBy {NodeId|UAObject} ( only provide componentOf or organizedBy but not both)
|
|
527
|
-
* @param [options.conditionClass =BaseConditionClassType] {NodeId|UAObject}
|
|
528
|
-
* The condition Class nodeId or object used to set the ConditionClassId and
|
|
529
|
-
* ConditionClassName properties of the condition.
|
|
530
|
-
*
|
|
531
|
-
* @param options.conditionSource {NodeId|UAObject} the condition source node.
|
|
532
|
-
* this node must be marked a EventSource.
|
|
533
|
-
* the conditionSource is used to populate the sourceNode and
|
|
534
|
-
* sourceName variables defined by BaseEventType
|
|
535
|
-
* @param options.conditionName {String} the condition Name
|
|
536
|
-
* @param [options.optionals] [Array<String>] an Array of optionals fields
|
|
537
|
-
*
|
|
538
|
-
* @param data a object containing the value to set
|
|
539
|
-
* @param data.eventId {String|NodeId} the EventType Identifier to instantiate (type cannot be abstract)
|
|
540
|
-
* @return a instantiated UAConditionEx
|
|
541
|
-
*/
|
|
542
|
-
function UACondition_instantiate(namespace, conditionTypeId, options, data) {
|
|
543
|
-
/* eslint max-statements: ["error", 100] */
|
|
544
|
-
const addressSpace = namespace.addressSpace;
|
|
545
|
-
const conditionType = addressSpace.findEventType(conditionTypeId);
|
|
546
|
-
/* istanbul ignore next */
|
|
547
|
-
if (!conditionType) {
|
|
548
|
-
throw new Error(" cannot find Condition Type for " + conditionTypeId);
|
|
549
|
-
}
|
|
550
|
-
// reminder : abstract event type cannot be instantiated directly !
|
|
551
|
-
(0, node_opcua_assert_1.assert)(!conditionType.isAbstract, "Cannot instantiate abstract conditionType");
|
|
552
|
-
const baseConditionEventType = addressSpace.findEventType("ConditionType");
|
|
553
|
-
/* istanbul ignore next */
|
|
554
|
-
if (!baseConditionEventType) {
|
|
555
|
-
throw new Error("cannot find ConditionType");
|
|
556
|
-
}
|
|
557
|
-
(0, node_opcua_assert_1.assert)(conditionType.isSupertypeOf(baseConditionEventType));
|
|
558
|
-
// assert((typeof options.browseName === "string"));
|
|
559
|
-
options.browseName = options.browseName || "??? instantiateCondition - missing browseName";
|
|
560
|
-
options.optionals = options.optionals || [];
|
|
561
|
-
// now optionals in 1.04
|
|
562
|
-
options.optionals.push("EventType");
|
|
563
|
-
options.optionals.push("BranchId");
|
|
564
|
-
//
|
|
565
|
-
options.optionals.push("Comment");
|
|
566
|
-
options.optionals.push("Comment.SourceTimestamp");
|
|
567
|
-
options.optionals.push("EnabledState.TrueState");
|
|
568
|
-
options.optionals.push("EnabledState.TrueState");
|
|
569
|
-
options.optionals.push("EnabledState.FalseState");
|
|
570
|
-
options.optionals.push("EnabledState.TransitionTime");
|
|
571
|
-
options.optionals.push("EnabledState.EffectiveTransitionTime");
|
|
572
|
-
options.optionals.push("EnabledState.EffectiveDisplayName");
|
|
573
|
-
const conditionNode = conditionType.instantiate(options);
|
|
574
|
-
Object.setPrototypeOf(conditionNode, UAConditionImpl.prototype);
|
|
575
|
-
conditionNode.initialize();
|
|
576
|
-
(0, node_opcua_assert_1.assert)(Object.prototype.hasOwnProperty.call(options, "conditionSource"), "must specify a condition source either as null or as a UAObject");
|
|
577
|
-
if (!options.conditionOf) {
|
|
578
|
-
options.conditionOf = options.conditionSource;
|
|
579
|
-
}
|
|
580
|
-
if (options.conditionOf) {
|
|
581
|
-
(0, node_opcua_assert_1.assert)(Object.prototype.hasOwnProperty.call(options, "conditionOf")); // must provide a conditionOf
|
|
582
|
-
options.conditionOf = addressSpace._coerceNode(options.conditionOf);
|
|
583
|
-
// HasCondition References can be used in the Type definition of an Object or a Variable.
|
|
584
|
-
(0, node_opcua_assert_1.assert)(options.conditionOf.nodeClass === node_opcua_data_model_1.NodeClass.Object || options.conditionOf.nodeClass === node_opcua_data_model_1.NodeClass.Variable);
|
|
585
|
-
conditionNode.addReference({
|
|
586
|
-
isForward: false,
|
|
587
|
-
nodeId: options.conditionOf,
|
|
588
|
-
referenceType: "HasCondition"
|
|
589
|
-
});
|
|
590
|
-
(0, node_opcua_assert_1.assert)(conditionNode.conditionOfNode().nodeId === options.conditionOf.nodeId);
|
|
591
|
-
}
|
|
592
|
-
// the constant property of this condition
|
|
593
|
-
conditionNode.eventType.setValueFromSource({
|
|
594
|
-
dataType: node_opcua_variant_1.DataType.NodeId,
|
|
595
|
-
value: conditionType.nodeId
|
|
596
|
-
});
|
|
597
|
-
data = data || {};
|
|
598
|
-
// install initial branch ID (null NodeId);
|
|
599
|
-
conditionNode.branchId.setValueFromSource({
|
|
600
|
-
dataType: node_opcua_variant_1.DataType.NodeId,
|
|
601
|
-
value: new node_opcua_nodeid_1.NodeId()
|
|
602
|
-
});
|
|
603
|
-
// install 'Comment' condition variable
|
|
604
|
-
_install_condition_variable_type(conditionNode.comment);
|
|
605
|
-
// install 'Quality' condition variable
|
|
606
|
-
_install_condition_variable_type(conditionNode.quality);
|
|
607
|
-
// xx conditionNode.quality.setValueFromSource({dataType: DataType.StatusCode,value: StatusCodes.Good });
|
|
608
|
-
// install 'LastSeverity' condition variable
|
|
609
|
-
_install_condition_variable_type(conditionNode.lastSeverity);
|
|
610
|
-
// xx conditionNode.severity.setValueFromSource({dataType: DataType.UInt16,value: 0 });
|
|
611
|
-
// xx conditionNode.lastSeverity.setValueFromSource({dataType: DataType.UInt16,value: 0 });
|
|
612
|
-
// install 'EnabledState' TwoStateVariable
|
|
613
|
-
/**
|
|
614
|
-
* @property enabledState
|
|
615
|
-
* @type {UATwoStateVariable}
|
|
616
|
-
*/
|
|
617
|
-
// -------------- fixing missing EnabledState.EffectiveDisplayName
|
|
618
|
-
if (!conditionNode.enabledState.effectiveDisplayName) {
|
|
619
|
-
namespace.addVariable({
|
|
620
|
-
browseName: new node_opcua_data_model_1.QualifiedName({ namespaceIndex: 0, name: "EffectiveDisplayName" }),
|
|
621
|
-
dataType: "LocalizedText",
|
|
622
|
-
propertyOf: conditionNode.enabledState
|
|
623
|
-
});
|
|
624
|
-
}
|
|
625
|
-
(0, ua_two_state_variable_1._install_TwoStateVariable_machinery)(conditionNode.enabledState, {
|
|
626
|
-
falseState: "Disabled",
|
|
627
|
-
trueState: "Enabled"
|
|
628
|
-
});
|
|
629
|
-
// installing sourceName and sourceNode
|
|
630
|
-
conditionNode.enabledState.setValue(true);
|
|
631
|
-
// set properties to in initial values
|
|
632
|
-
Object.entries(data).forEach(([key, value]) => {
|
|
633
|
-
const varNode = _getCompositeKey(conditionNode, key);
|
|
634
|
-
(0, node_opcua_assert_1.assert)(varNode.nodeClass === node_opcua_data_model_1.NodeClass.Variable);
|
|
635
|
-
const variant = new node_opcua_variant_1.Variant(value);
|
|
636
|
-
// check that Variant DataType is compatible with the UAVariable dataType
|
|
637
|
-
// xx var nodeDataType = addressSpace.findNode(varNode.dataType).browseName;
|
|
638
|
-
/* istanbul ignore next */
|
|
639
|
-
if (!varNode._validate_DataType(variant.dataType)) {
|
|
640
|
-
throw new Error(" Invalid variant dataType " + variant + " " + varNode.browseName.toString());
|
|
641
|
-
}
|
|
642
|
-
varNode.setValueFromSource(variant);
|
|
643
|
-
});
|
|
644
|
-
// bind condition methods -
|
|
645
|
-
/**
|
|
646
|
-
* @property enable
|
|
647
|
-
* @type {UAMethod}
|
|
648
|
-
*/
|
|
649
|
-
conditionNode.enable.bindMethod(_enable_method);
|
|
650
|
-
/**
|
|
651
|
-
* @property disable
|
|
652
|
-
* @type {UAMethod}
|
|
653
|
-
*/
|
|
654
|
-
conditionNode.disable.bindMethod(_disable_method);
|
|
655
|
-
// bind condition methods - AddComment
|
|
656
|
-
/**
|
|
657
|
-
* @property addComment
|
|
658
|
-
* @type {UAMethod}
|
|
659
|
-
*/
|
|
660
|
-
conditionNode.addComment.bindMethod(_add_comment_method);
|
|
661
|
-
(0, node_opcua_assert_1.assert)(conditionNode instanceof UAConditionImpl);
|
|
662
|
-
// ConditionSource => cf SourceNode
|
|
663
|
-
// As per spec OPCUA 1.03 part 9 page 54:
|
|
664
|
-
// The ConditionType inherits all Properties of the BaseEventType. Their semantic is defined in
|
|
665
|
-
// Part 5. SourceNode identifies the ConditionSource.
|
|
666
|
-
// The SourceNode is the Node which the condition is associated with, it may be the same as the
|
|
667
|
-
// InputNode for an alarm, but it may be a separate node. For example a motor, which is a
|
|
668
|
-
// variable with a value that is an RPM, may be the ConditionSource for Conditions that are
|
|
669
|
-
// related to the motor as well as a temperature sensor associated with the motor. In the former
|
|
670
|
-
// the InputNode for the High RPM alarm is the value of the Motor RPM, while in the later the
|
|
671
|
-
// InputNode of the High Alarm would be the value of the temperature sensor that is associated
|
|
672
|
-
// with the motor.
|
|
673
|
-
if (options.conditionSource) {
|
|
674
|
-
options.conditionSource = addressSpace._coerceNode(options.conditionSource);
|
|
675
|
-
if (options.conditionSource.nodeClass !== node_opcua_data_model_1.NodeClass.Object && options.conditionSource.nodeClass !== node_opcua_data_model_1.NodeClass.Variable) {
|
|
676
|
-
// tslint:disable:no-console
|
|
677
|
-
console.log(options.conditionSource);
|
|
678
|
-
throw new Error("Expecting condition source to be NodeClass.Object or Variable");
|
|
679
|
-
}
|
|
680
|
-
const conditionSourceNode = addressSpace.findNode(options.conditionSource.nodeId);
|
|
681
|
-
if (conditionSourceNode) {
|
|
682
|
-
conditionNode.sourceNode.setValueFromSource({
|
|
683
|
-
dataType: node_opcua_variant_1.DataType.NodeId,
|
|
684
|
-
value: conditionSourceNode.nodeId
|
|
685
|
-
});
|
|
686
|
-
// conditionSourceNode node must be registered as a EventSource of an other node.
|
|
687
|
-
// As per spec OPCUA 1.03 part 9 page 54:
|
|
688
|
-
// HasNotifier and HasEventSource References are used to expose the hierarchical organization
|
|
689
|
-
// of Event notifying Objects and ConditionSources. An Event notifying Object represents
|
|
690
|
-
// typically an area of Operator responsibility. The definition of such an area configuration is
|
|
691
|
-
// outside the scope of this standard. If areas are available they shall be linked together and
|
|
692
|
-
// with the included ConditionSources using the HasNotifier and the HasEventSource Reference
|
|
693
|
-
// Types. The Server Object shall be the root of this hierarchy.
|
|
694
|
-
if (!(0, node_opcua_nodeid_1.sameNodeId)(conditionSourceNode.nodeId, (0, node_opcua_nodeid_1.coerceNodeId)("ns=0;i=2253"))) {
|
|
695
|
-
// server object
|
|
696
|
-
/* istanbul ignore next */
|
|
697
|
-
if (conditionSourceNode.getEventSourceOfs().length === 0) {
|
|
698
|
-
errorLog("conditionSourceNode = ", conditionSourceNode.browseName.toString());
|
|
699
|
-
errorLog("conditionSourceNode = ", conditionSourceNode.nodeId.toString());
|
|
700
|
-
throw new Error("conditionSourceNode must be an event source " +
|
|
701
|
-
conditionSourceNode.browseName.toString() +
|
|
702
|
-
conditionSourceNode.nodeId.toString());
|
|
703
|
-
}
|
|
704
|
-
}
|
|
705
|
-
// set source Node (defined in UABaseEventType)
|
|
706
|
-
conditionNode.sourceNode.setValueFromSource(conditionSourceNode.readAttribute(null, node_opcua_data_model_1.AttributeIds.NodeId).value);
|
|
707
|
-
// set source Name (defined in UABaseEventType)
|
|
708
|
-
const displayName = conditionSourceNode.readAttribute(null, node_opcua_data_model_1.AttributeIds.DisplayName).value
|
|
709
|
-
.value;
|
|
710
|
-
conditionNode.sourceName.setValueFromSource({ dataType: node_opcua_variant_1.DataType.String, value: displayName.text });
|
|
711
|
-
}
|
|
712
|
-
}
|
|
713
|
-
conditionNode.eventType.setValueFromSource({
|
|
714
|
-
dataType: node_opcua_variant_1.DataType.NodeId,
|
|
715
|
-
value: conditionType.nodeId
|
|
716
|
-
});
|
|
717
|
-
// as per spec:
|
|
718
|
-
/**
|
|
719
|
-
*
|
|
720
|
-
* dataType: DataType.NodeId
|
|
721
|
-
*
|
|
722
|
-
* As per spec OPCUA 1.03 part 9:
|
|
723
|
-
* ConditionClassId specifies in which domain this Condition is used. It is the NodeId of the
|
|
724
|
-
* corresponding ConditionClassType. See 5.9 for the definition of ConditionClass and a set of
|
|
725
|
-
* ConditionClasses defined in this standard. When using this Property for filtering, Clients have
|
|
726
|
-
* to specify all individual ConditionClassType NodeIds. The OfType operator cannot be applied.
|
|
727
|
-
* BaseConditionClassType is used as class whenever a Condition cannot be assigned to a
|
|
728
|
-
* more concrete class.
|
|
729
|
-
*
|
|
730
|
-
* BaseConditionClassType
|
|
731
|
-
* |
|
|
732
|
-
* +---------------------------+----------------------------+
|
|
733
|
-
* | | |
|
|
734
|
-
* ProcessConditionClassType MaintenanceConditionClassType SystemConditionClassType
|
|
735
|
-
*
|
|
736
|
-
* @property conditionName
|
|
737
|
-
* @type {UAVariable}
|
|
738
|
-
*/
|
|
739
|
-
const baseConditionClassType = addressSpace.findObjectType("ProcessConditionClassType");
|
|
740
|
-
// assert(baseConditionClassType,"Expecting BaseConditionClassType to be in addressSpace");
|
|
741
|
-
let conditionClassId = baseConditionClassType ? baseConditionClassType.nodeId : new node_opcua_nodeid_1.NodeId();
|
|
742
|
-
let conditionClassName = baseConditionClassType ? baseConditionClassType.displayName[0] : "";
|
|
743
|
-
if (options.conditionClass) {
|
|
744
|
-
if (typeof options.conditionClass === "string") {
|
|
745
|
-
options.conditionClass = addressSpace.findObjectType(options.conditionClass);
|
|
746
|
-
if (!options.conditionClass) {
|
|
747
|
-
throw new Error("cannot find condition class " + options.conditionClass);
|
|
748
|
-
}
|
|
749
|
-
}
|
|
750
|
-
const conditionClassNode = addressSpace._coerceNode(options.conditionClass);
|
|
751
|
-
if (!conditionClassNode) {
|
|
752
|
-
throw new Error("cannot find condition class " + options.conditionClass.toString());
|
|
753
|
-
}
|
|
754
|
-
conditionClassId = conditionClassNode.nodeId;
|
|
755
|
-
conditionClassName = conditionClassNode.displayName[0];
|
|
756
|
-
}
|
|
757
|
-
conditionNode.conditionClassId.setValueFromSource({
|
|
758
|
-
dataType: node_opcua_variant_1.DataType.NodeId,
|
|
759
|
-
value: conditionClassId
|
|
760
|
-
});
|
|
761
|
-
// as per spec:
|
|
762
|
-
// ConditionClassName provides the display name of the ConditionClassType.
|
|
763
|
-
conditionNode.conditionClassName.setValueFromSource({
|
|
764
|
-
dataType: node_opcua_variant_1.DataType.LocalizedText,
|
|
765
|
-
value: (0, node_opcua_data_model_1.coerceLocalizedText)(conditionClassName)
|
|
766
|
-
});
|
|
767
|
-
// as per spec:
|
|
768
|
-
/**
|
|
769
|
-
*
|
|
770
|
-
* dataType: DataType.String
|
|
771
|
-
*
|
|
772
|
-
* As per spec OPCUA 1.03 part 9:
|
|
773
|
-
* ConditionName identifies the Condition instance that the Event originated from. It can be used
|
|
774
|
-
* together with the SourceName in a user display to distinguish between different Condition
|
|
775
|
-
* instances. If a ConditionSource has only one instance of a ConditionType, and the Server has
|
|
776
|
-
* no instance name, the Server shall supply the ConditionType browse name.
|
|
777
|
-
* @property conditionName
|
|
778
|
-
* @type {UAVariable}
|
|
779
|
-
*/
|
|
780
|
-
const conditionName = options.conditionName || "Unset Condition Name";
|
|
781
|
-
(0, node_opcua_assert_1.assert)(typeof conditionName === "string");
|
|
782
|
-
conditionNode.conditionName.setValueFromSource({
|
|
783
|
-
dataType: node_opcua_variant_1.DataType.String,
|
|
784
|
-
value: conditionName
|
|
785
|
-
});
|
|
786
|
-
// set SourceNode and SourceName based on HasCondition node
|
|
787
|
-
const sourceNodes = conditionNode.findReferencesAsObject("HasCondition", false);
|
|
788
|
-
if (sourceNodes.length) {
|
|
789
|
-
(0, node_opcua_assert_1.assert)(sourceNodes.length === 1);
|
|
790
|
-
conditionNode.setSourceNode(sourceNodes[0].nodeId);
|
|
791
|
-
conditionNode.setSourceName(sourceNodes[0].browseName.toString());
|
|
792
|
-
}
|
|
793
|
-
conditionNode.post_initialize();
|
|
794
|
-
const branch0 = conditionNode.currentBranch();
|
|
795
|
-
branch0.setRetain(false);
|
|
796
|
-
branch0.setComment("");
|
|
797
|
-
branch0.setQuality(node_opcua_status_code_1.StatusCodes.Good);
|
|
798
|
-
branch0.setSeverity(0);
|
|
799
|
-
branch0.setLocalTime(new node_opcua_types_1.TimeZoneDataType({
|
|
800
|
-
daylightSavingInOffset: false,
|
|
801
|
-
offset: 0
|
|
802
|
-
}));
|
|
803
|
-
branch0.setMessage("");
|
|
804
|
-
branch0.setReceiveTime(node_opcua_basic_types_2.minDate);
|
|
805
|
-
branch0.setTime(node_opcua_basic_types_2.minDate);
|
|
806
|
-
return conditionNode;
|
|
807
|
-
}
|
|
808
|
-
function _disable_method(inputArguments, context, callback) {
|
|
809
|
-
(0, node_opcua_assert_1.assert)(inputArguments.length === 0);
|
|
810
|
-
const conditionNode = context.object;
|
|
811
|
-
(0, node_opcua_assert_1.assert)(conditionNode);
|
|
812
|
-
// istanbul ignore next
|
|
813
|
-
if (!(conditionNode instanceof UAConditionImpl)) {
|
|
814
|
-
console.log("conditionNode is not a UACondition ", conditionNode === null || conditionNode === void 0 ? void 0 : conditionNode.toString());
|
|
815
|
-
return callback(null, {
|
|
816
|
-
statusCode: node_opcua_status_code_1.StatusCodes.BadNodeIdInvalid
|
|
817
|
-
});
|
|
818
|
-
}
|
|
819
|
-
const statusCode = conditionNode._setEnabledState(false);
|
|
820
|
-
return callback(null, {
|
|
821
|
-
statusCode
|
|
822
|
-
});
|
|
823
|
-
}
|
|
824
|
-
function _enable_method(inputArguments, context, callback) {
|
|
825
|
-
(0, node_opcua_assert_1.assert)(inputArguments.length === 0);
|
|
826
|
-
const conditionNode = context.object;
|
|
827
|
-
(0, node_opcua_assert_1.assert)(conditionNode);
|
|
828
|
-
if (!(conditionNode instanceof UAConditionImpl)) {
|
|
829
|
-
return callback(null, {
|
|
830
|
-
statusCode: node_opcua_status_code_1.StatusCodes.BadNodeIdInvalid
|
|
831
|
-
});
|
|
832
|
-
}
|
|
833
|
-
const statusCode = conditionNode._setEnabledState(true);
|
|
834
|
-
return callback(null, {
|
|
835
|
-
statusCode
|
|
836
|
-
});
|
|
837
|
-
}
|
|
838
|
-
function _condition_refresh_method(inputArguments, context, callback) {
|
|
839
|
-
// arguments : IntegerId SubscriptionId
|
|
840
|
-
(0, node_opcua_assert_1.assert)(inputArguments.length === 1);
|
|
841
|
-
const addressSpace = context.object.addressSpace;
|
|
842
|
-
if (doDebug) {
|
|
843
|
-
debugLog(chalk.red(" ConditionType.ConditionRefresh ! subscriptionId ="), inputArguments[0].toString());
|
|
844
|
-
}
|
|
845
|
-
const subscriptionId = inputArguments[0].value;
|
|
846
|
-
let statusCode = _check_subscription_id_is_valid(subscriptionId, context);
|
|
847
|
-
if (statusCode !== node_opcua_status_code_1.StatusCodes.Good) {
|
|
848
|
-
return statusCode;
|
|
849
|
-
}
|
|
850
|
-
statusCode = _perform_condition_refresh(addressSpace, inputArguments, context);
|
|
851
|
-
return callback(null, {
|
|
852
|
-
statusCode
|
|
853
|
-
});
|
|
854
|
-
}
|
|
855
|
-
function _perform_condition_refresh(addressSpace, inputArguments, context) {
|
|
856
|
-
// --- possible StatusCodes:
|
|
857
|
-
//
|
|
858
|
-
// Bad_SubscriptionIdInvalid See Part 4 for the description of this result code
|
|
859
|
-
// Bad_RefreshInProgress See Table 74 for the description of this result code
|
|
860
|
-
// Bad_UserAccessDenied The Method was not called in the context of the Session
|
|
861
|
-
// that owns the Subscription
|
|
862
|
-
//
|
|
863
|
-
// istanbul ignore next
|
|
864
|
-
if (addressSpace._condition_refresh_in_progress) {
|
|
865
|
-
// a refresh operation is already in progress....
|
|
866
|
-
return node_opcua_status_code_1.StatusCodes.BadRefreshInProgress;
|
|
867
|
-
}
|
|
868
|
-
addressSpace._condition_refresh_in_progress = true;
|
|
869
|
-
const server = context.object.addressSpace.rootFolder.objects.server;
|
|
870
|
-
const refreshStartEventType = addressSpace.findEventType("RefreshStartEventType");
|
|
871
|
-
const refreshEndEventType = addressSpace.findEventType("RefreshEndEventType");
|
|
872
|
-
server.raiseEvent(refreshStartEventType, {});
|
|
873
|
-
// todo : resend retained conditions
|
|
874
|
-
const _server = server;
|
|
875
|
-
// starting from server object ..
|
|
876
|
-
// evaluated all --> hasNotifier/hasEventSource -> node
|
|
877
|
-
_server._conditionRefresh();
|
|
878
|
-
server.raiseEvent(refreshEndEventType, {});
|
|
879
|
-
addressSpace._condition_refresh_in_progress = false;
|
|
880
|
-
return node_opcua_status_code_1.StatusCodes.Good;
|
|
881
|
-
}
|
|
882
|
-
function _condition_refresh2_method(inputArguments, context, callback) {
|
|
883
|
-
// arguments : IntegerId SubscriptionId
|
|
884
|
-
// arguments : IntegerId MonitoredItemId
|
|
885
|
-
(0, node_opcua_assert_1.assert)(inputArguments.length === 2);
|
|
886
|
-
if (!context.object) {
|
|
887
|
-
throw new Error("Invalid context => missing Object");
|
|
888
|
-
}
|
|
889
|
-
const addressSpace = context.object.addressSpace;
|
|
890
|
-
// istanbul ignore next
|
|
891
|
-
if (doDebug) {
|
|
892
|
-
debugLog(chalk.cyan.bgWhite(" ConditionType.conditionRefresh2 !"));
|
|
893
|
-
}
|
|
894
|
-
// xx var subscriptionId = inputArguments[0].value;
|
|
895
|
-
// xx var monitoredItemId = inputArguments[1].value;
|
|
896
|
-
const statusCode = _perform_condition_refresh(addressSpace, inputArguments, context);
|
|
897
|
-
return callback(null, {
|
|
898
|
-
statusCode
|
|
899
|
-
});
|
|
900
|
-
}
|
|
901
|
-
function _add_comment_method(inputArguments, context, callback) {
|
|
902
|
-
//
|
|
903
|
-
// The AddComment Method is used to apply a comment to a specific state of a Condition
|
|
904
|
-
// instance. Normally, the NodeId of the Object instance is passed as the ObjectId to the Call
|
|
905
|
-
// Service. However, some Servers do not expose Condition instances in the AddressSpace.
|
|
906
|
-
// Therefore, all Servers shall also allow Clients to call the AddComment Method by specifying
|
|
907
|
-
// ConditionId as the ObjectId. The Method cannot be called with an ObjectId of the
|
|
908
|
-
// ConditionType Node.
|
|
909
|
-
// Signature
|
|
910
|
-
// - EventId EventId identifying a particular Event Notification where a state was reported for a
|
|
911
|
-
// Condition.
|
|
912
|
-
// - Comment A localized text to be applied to the Condition.
|
|
913
|
-
//
|
|
914
|
-
// AlwaysGeneratesEvent AuditConditionCommentEventType
|
|
915
|
-
//
|
|
916
|
-
UAConditionImpl.with_condition_method(inputArguments, context, callback, (conditionEventId, comment, branch, conditionNode) => {
|
|
917
|
-
(0, node_opcua_assert_1.assert)(inputArguments instanceof Array);
|
|
918
|
-
(0, node_opcua_assert_1.assert)(conditionEventId instanceof Buffer || conditionEventId === null);
|
|
919
|
-
(0, node_opcua_assert_1.assert)(branch instanceof condition_snapshot_impl_1.ConditionSnapshotImpl);
|
|
920
|
-
branch.setComment(comment);
|
|
921
|
-
const sourceName = "Method/AddComment";
|
|
922
|
-
conditionNode._raiseAuditConditionCommentEvent(sourceName, conditionEventId, comment);
|
|
923
|
-
// raise new event
|
|
924
|
-
conditionNode.raiseConditionEvent(branch, true);
|
|
925
|
-
/**
|
|
926
|
-
* raised when the branch has been added a comment
|
|
927
|
-
* @event addComment
|
|
928
|
-
* @param conditionEventId NodeId|null
|
|
929
|
-
* @param comment {LocalizedText}
|
|
930
|
-
* @param branch {ConditionSnapshot}
|
|
931
|
-
*/
|
|
932
|
-
conditionNode.emit("addComment", conditionEventId, comment, branch);
|
|
933
|
-
return node_opcua_status_code_1.StatusCodes.Good;
|
|
934
|
-
});
|
|
935
|
-
}
|
|
936
|
-
function sameBuffer(b1, b2) {
|
|
937
|
-
if (!b1 && !b2) {
|
|
938
|
-
return true;
|
|
939
|
-
}
|
|
940
|
-
if (b1 && !b2) {
|
|
941
|
-
return false;
|
|
942
|
-
}
|
|
943
|
-
if (!b1 && b2) {
|
|
944
|
-
return false;
|
|
945
|
-
}
|
|
946
|
-
(0, node_opcua_assert_1.assert)(b1 instanceof Buffer);
|
|
947
|
-
(0, node_opcua_assert_1.assert)(b2 instanceof Buffer);
|
|
948
|
-
if (b1.length !== b2.length) {
|
|
949
|
-
return false;
|
|
950
|
-
}
|
|
951
|
-
/*
|
|
952
|
-
var bb1 = (Buffer.from(b1)).toString("hex");
|
|
953
|
-
var bb2 = (Buffer.from(b2)).toString("hex");
|
|
954
|
-
return bb1 === bb2;
|
|
955
|
-
*/
|
|
956
|
-
const n = b1.length;
|
|
957
|
-
for (let i = 0; i < n; i++) {
|
|
958
|
-
if (b1[i] !== b2[i]) {
|
|
959
|
-
return false;
|
|
960
|
-
}
|
|
961
|
-
}
|
|
962
|
-
return true;
|
|
963
|
-
}
|
|
964
|
-
function _create_new_branch_id() {
|
|
965
|
-
return (0, node_opcua_nodeid_1.makeNodeId)((0, node_opcua_basic_types_1.randomGuid)(), 1);
|
|
966
|
-
}
|
|
967
|
-
function _update_sourceTimestamp(dataValue /*, indexRange*/) {
|
|
968
|
-
this.sourceTimestamp.setValueFromSource({
|
|
969
|
-
dataType: node_opcua_variant_1.DataType.DateTime,
|
|
970
|
-
value: dataValue.sourceTimestamp
|
|
971
|
-
});
|
|
972
|
-
}
|
|
973
|
-
// tslint:disable:no-console
|
|
974
|
-
function _install_condition_variable_type(node) {
|
|
975
|
-
// from spec 1.03 : 5.3 condition variables
|
|
976
|
-
// However, a change in their value is considered important and supposed to trigger
|
|
977
|
-
// an Event Notification. These information elements are called ConditionVariables.
|
|
978
|
-
if (node.sourceTimestamp) {
|
|
979
|
-
node.sourceTimestamp.accessLevel = (0, node_opcua_data_model_1.makeAccessLevelFlag)("CurrentRead");
|
|
980
|
-
}
|
|
981
|
-
else {
|
|
982
|
-
console.warn("cannot find node.sourceTimestamp", node.browseName.toString());
|
|
983
|
-
}
|
|
984
|
-
node.accessLevel = (0, node_opcua_data_model_1.makeAccessLevelFlag)("CurrentRead");
|
|
985
|
-
// from spec 1.03 : 5.3 condition variables
|
|
986
|
-
// a condition VariableType has a sourceTimeStamp exposed property
|
|
987
|
-
// SourceTimestamp indicates the time of the last change of the Value of this ConditionVariable.
|
|
988
|
-
// It shall be the same time that would be returned from the Read Service inside the DataValue
|
|
989
|
-
// structure for the ConditionVariable Value Attribute.
|
|
990
|
-
(0, node_opcua_assert_1.assert)(node.typeDefinitionObj.browseName.toString() === "ConditionVariableType");
|
|
991
|
-
(0, node_opcua_assert_1.assert)(node.sourceTimestamp.browseName.toString() === "SourceTimestamp");
|
|
992
|
-
node.on("value_changed", _update_sourceTimestamp);
|
|
993
|
-
}
|
|
994
|
-
/**
|
|
995
|
-
* @method _getCompositeKey
|
|
996
|
-
* @param node {BaseNode}
|
|
997
|
-
* @param key {String}
|
|
998
|
-
* @return {BaseNode}
|
|
999
|
-
* @private
|
|
1000
|
-
*
|
|
1001
|
-
* @example
|
|
1002
|
-
*
|
|
1003
|
-
* var node = _getComposite(node,"enabledState.id");
|
|
1004
|
-
*
|
|
1005
|
-
*/
|
|
1006
|
-
function _getCompositeKey(node, key) {
|
|
1007
|
-
let cur = node;
|
|
1008
|
-
const elements = key.split(".");
|
|
1009
|
-
for (const e of elements) {
|
|
1010
|
-
// istanbul ignore next
|
|
1011
|
-
if (!Object.prototype.hasOwnProperty.call(cur, e)) {
|
|
1012
|
-
throw new Error(" cannot extract '" + key + "' from " + node.browseName.toString());
|
|
1013
|
-
}
|
|
1014
|
-
cur = cur[e];
|
|
1015
|
-
}
|
|
1016
|
-
return cur;
|
|
1017
|
-
}
|
|
1018
|
-
/**
|
|
1019
|
-
* verify that the subscription id belongs to the session that make the call.
|
|
1020
|
-
* @method _check_subscription_id_is_valid
|
|
1021
|
-
* @param subscriptionId {Number}
|
|
1022
|
-
* @param context {Object}
|
|
1023
|
-
* @private
|
|
1024
|
-
*/
|
|
1025
|
-
function _check_subscription_id_is_valid(subscriptionId, context) {
|
|
1026
|
-
/// todo: return StatusCodes.BadSubscriptionIdInvalid; if subscriptionId doesn't belong to session...
|
|
1027
|
-
return node_opcua_status_code_1.StatusCodes.Good;
|
|
1028
|
-
}
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.UAConditionImpl = void 0;
|
|
4
|
+
/* eslint-disable complexity */
|
|
5
|
+
/**
|
|
6
|
+
* @module node-opcua-address-space.AlarmsAndConditions
|
|
7
|
+
*/
|
|
8
|
+
const chalk = require("chalk");
|
|
9
|
+
const node_opcua_assert_1 = require("node-opcua-assert");
|
|
10
|
+
const node_opcua_basic_types_1 = require("node-opcua-basic-types");
|
|
11
|
+
const node_opcua_data_model_1 = require("node-opcua-data-model");
|
|
12
|
+
const node_opcua_debug_1 = require("node-opcua-debug");
|
|
13
|
+
const node_opcua_basic_types_2 = require("node-opcua-basic-types");
|
|
14
|
+
const node_opcua_nodeid_1 = require("node-opcua-nodeid");
|
|
15
|
+
const node_opcua_status_code_1 = require("node-opcua-status-code");
|
|
16
|
+
const node_opcua_types_1 = require("node-opcua-types");
|
|
17
|
+
const node_opcua_variant_1 = require("node-opcua-variant");
|
|
18
|
+
const ua_two_state_variable_1 = require("../state_machine/ua_two_state_variable");
|
|
19
|
+
const ua_object_impl_1 = require("../ua_object_impl");
|
|
20
|
+
const ua_base_event_impl_1 = require("./ua_base_event_impl");
|
|
21
|
+
const condition_snapshot_impl_1 = require("./condition_snapshot_impl");
|
|
22
|
+
const debugLog = (0, node_opcua_debug_1.make_debugLog)(__filename);
|
|
23
|
+
const errorLog = (0, node_opcua_debug_1.make_errorLog)(__filename);
|
|
24
|
+
const doDebug = (0, node_opcua_debug_1.checkDebugFlag)(__filename);
|
|
25
|
+
const warningLog = (0, node_opcua_debug_1.make_warningLog)(__filename);
|
|
26
|
+
/**
|
|
27
|
+
*
|
|
28
|
+
* └─ ConditionType
|
|
29
|
+
* ├─ DialogConditionType
|
|
30
|
+
* └─ AcknowledgeableConditionType
|
|
31
|
+
* └─ AlarmConditionType
|
|
32
|
+
* ├─ LimitAlarmType
|
|
33
|
+
* │ ├─ ExclusiveLimitAlarmType
|
|
34
|
+
* │ │ ├─ ExclusiveLevelAlarmType
|
|
35
|
+
* │ │ ├─ ExclusiveDeviationAlarmType
|
|
36
|
+
* │ │ └─ ExclusiveRateOfChangeAlarmType
|
|
37
|
+
* │ └─ NonExclusiveLimitAlarmType
|
|
38
|
+
* │ ├─ NonExclusiveLevelAlarmType
|
|
39
|
+
* │ ├─ NonExclusiveDeviationAlarmType
|
|
40
|
+
* │ └─ NonExclusiveRateOfChangeAlarmType
|
|
41
|
+
* └─ DiscreteAlarmType
|
|
42
|
+
* ├─ OffNormalAlarmType
|
|
43
|
+
* │ ├─ SystemOffNormalAlarmType
|
|
44
|
+
* │ │ └─ CertificateExpirationAlarmType
|
|
45
|
+
* │ └─ TripAlarmType
|
|
46
|
+
*
|
|
47
|
+
*/
|
|
48
|
+
class UAConditionImpl extends ua_base_event_impl_1.UABaseEventImpl {
|
|
49
|
+
constructor() {
|
|
50
|
+
super(...arguments);
|
|
51
|
+
this._branch0 = null;
|
|
52
|
+
this._previousRetainFlag = false;
|
|
53
|
+
this._branches = {};
|
|
54
|
+
}
|
|
55
|
+
static instantiate(namespace, conditionTypeId, options, data) {
|
|
56
|
+
return UACondition_instantiate(namespace, conditionTypeId, options, data);
|
|
57
|
+
}
|
|
58
|
+
static install_condition_refresh_handle(addressSpace) {
|
|
59
|
+
//
|
|
60
|
+
// install ConditionRefresh
|
|
61
|
+
//
|
|
62
|
+
// NOTE:
|
|
63
|
+
// OPCUA doesn't implement the condition refresh method ! yet
|
|
64
|
+
// .5.7 ConditionRefresh Method
|
|
65
|
+
// ConditionRefresh allows a Client to request a Refresh of all Condition instances that currently
|
|
66
|
+
// are in an interesting state (they have the Retain flag set). This includes previous states of a
|
|
67
|
+
// Condition instance for which the Server maintains Branches. A Client would typically invoke
|
|
68
|
+
// this Method when it initially connects to a Server and following any situations, such as
|
|
69
|
+
// communication disruptions, in which it would require resynchronization with the Server. This
|
|
70
|
+
// Method is only available on the ConditionType or its subtypes. To invoke this Method, the call
|
|
71
|
+
// shall pass the well known MethodId of the Method on the ConditionType and the ObjectId
|
|
72
|
+
// shall be the well known ObjectId of the ConditionType Object.
|
|
73
|
+
const conditionType = addressSpace.findEventType("ConditionType");
|
|
74
|
+
(0, node_opcua_assert_1.assert)(conditionType !== null);
|
|
75
|
+
conditionType.disable.bindMethod(_disable_method);
|
|
76
|
+
conditionType.enable.bindMethod(_enable_method);
|
|
77
|
+
conditionType.conditionRefresh.bindMethod(_condition_refresh_method);
|
|
78
|
+
conditionType.conditionRefresh2.bindMethod(_condition_refresh2_method);
|
|
79
|
+
// those methods can be call on the ConditionType or on the ConditionInstance itself...
|
|
80
|
+
conditionType.addComment.bindMethod(_add_comment_method);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
*
|
|
84
|
+
* Helper method to handle condition methods that takes a branchId and a comment
|
|
85
|
+
*
|
|
86
|
+
*/
|
|
87
|
+
static with_condition_method(inputArguments, context, callback, inner_func) {
|
|
88
|
+
const conditionNode = context.object;
|
|
89
|
+
// xx console.log(inputArguments.map(function(a){return a.toString()}));
|
|
90
|
+
if (!(conditionNode instanceof UAConditionImpl)) {
|
|
91
|
+
callback(null, {
|
|
92
|
+
statusCode: node_opcua_status_code_1.StatusCodes.BadNodeIdInvalid
|
|
93
|
+
});
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
if (!conditionNode.getEnabledState()) {
|
|
97
|
+
callback(null, {
|
|
98
|
+
statusCode: node_opcua_status_code_1.StatusCodes.BadConditionDisabled
|
|
99
|
+
});
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
// inputArguments has 2 arguments
|
|
103
|
+
// EventId => ByteString The Identifier of the event to comment
|
|
104
|
+
// Comment => LocalizedText The Comment to add to the condition
|
|
105
|
+
(0, node_opcua_assert_1.assert)(inputArguments.length === 2);
|
|
106
|
+
(0, node_opcua_assert_1.assert)(inputArguments[0].dataType === node_opcua_variant_1.DataType.ByteString);
|
|
107
|
+
(0, node_opcua_assert_1.assert)(inputArguments[1].dataType === node_opcua_variant_1.DataType.LocalizedText);
|
|
108
|
+
const eventId = inputArguments[0].value;
|
|
109
|
+
(0, node_opcua_assert_1.assert)(!eventId || eventId instanceof Buffer);
|
|
110
|
+
const comment = inputArguments[1].value;
|
|
111
|
+
(0, node_opcua_assert_1.assert)(comment instanceof node_opcua_data_model_1.LocalizedText);
|
|
112
|
+
const branch = conditionNode._findBranchForEventId(eventId);
|
|
113
|
+
if (!branch) {
|
|
114
|
+
callback(null, {
|
|
115
|
+
statusCode: node_opcua_status_code_1.StatusCodes.BadEventIdUnknown
|
|
116
|
+
});
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
(0, node_opcua_assert_1.assert)(branch instanceof condition_snapshot_impl_1.ConditionSnapshotImpl);
|
|
120
|
+
const statusCode = inner_func(eventId, comment, branch, conditionNode);
|
|
121
|
+
// record also who did the call
|
|
122
|
+
branch.setClientUserId(context.userIdentity || "<unknown client user id>");
|
|
123
|
+
callback(null, {
|
|
124
|
+
statusCode
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* @method initialize
|
|
129
|
+
* @private
|
|
130
|
+
*/
|
|
131
|
+
initialize() {
|
|
132
|
+
this._branches = {};
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* @method post_initialize
|
|
136
|
+
* @private
|
|
137
|
+
*/
|
|
138
|
+
post_initialize() {
|
|
139
|
+
(0, node_opcua_assert_1.assert)(!this._branch0);
|
|
140
|
+
this._branch0 = new condition_snapshot_impl_1.ConditionSnapshotImpl(this, new node_opcua_nodeid_1.NodeId());
|
|
141
|
+
// the condition OPCUA object alway reflects the default branch states
|
|
142
|
+
// so we set a mechanism that automatically keeps self in sync
|
|
143
|
+
// with the default branch.
|
|
144
|
+
// the implication of this convention is that interacting with the condition variable
|
|
145
|
+
// shall be made by using branch0, any value change made
|
|
146
|
+
// using the standard setValueFromSource mechanism will not be work properly.
|
|
147
|
+
this._branch0.on("value_changed", (node, variant) => {
|
|
148
|
+
(0, node_opcua_assert_1.assert)(node.nodeClass === node_opcua_data_model_1.NodeClass.Variable);
|
|
149
|
+
node.setValueFromSource(variant);
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
getBranchCount() {
|
|
153
|
+
return Object.keys(this._branches).length;
|
|
154
|
+
}
|
|
155
|
+
getBranches() {
|
|
156
|
+
return Object.keys(this._branches).map((x) => {
|
|
157
|
+
return this._branches[x];
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
getBranchIds() {
|
|
161
|
+
return this.getBranches().map((b) => b.getBranchId());
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* @method createBranch
|
|
165
|
+
* @return {ConditionSnapshot}
|
|
166
|
+
*/
|
|
167
|
+
createBranch() {
|
|
168
|
+
const branchId = _create_new_branch_id();
|
|
169
|
+
const snapshot = new condition_snapshot_impl_1.ConditionSnapshotImpl(this, branchId);
|
|
170
|
+
this._branches[branchId.toString()] = snapshot;
|
|
171
|
+
return snapshot;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* @method deleteBranch
|
|
175
|
+
* @param branch {ConditionSnapshot}
|
|
176
|
+
*/
|
|
177
|
+
deleteBranch(branch) {
|
|
178
|
+
const key = branch.getBranchId().toString();
|
|
179
|
+
(0, node_opcua_assert_1.assert)(!(0, node_opcua_nodeid_1.sameNodeId)(branch.getBranchId(), node_opcua_nodeid_1.NodeId.nullNodeId), "cannot delete branch zero");
|
|
180
|
+
(0, node_opcua_assert_1.assert)(Object.prototype.hasOwnProperty.call(this._branches, key));
|
|
181
|
+
delete this._branches[key];
|
|
182
|
+
this.emit("branch_deleted", key);
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* @method getEnabledState
|
|
186
|
+
* @return {Boolean}
|
|
187
|
+
*/
|
|
188
|
+
getEnabledState() {
|
|
189
|
+
return this.enabledState.getValue();
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* @method getEnabledStateAsString
|
|
193
|
+
* @return {String}
|
|
194
|
+
*/
|
|
195
|
+
getEnabledStateAsString() {
|
|
196
|
+
return this.enabledState.getValueAsString();
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* returns {StatusCode} StatusCodes.Good if successful or BadConditionAlreadyEnabled/BadConditionAlreadyDisabled
|
|
200
|
+
* @private
|
|
201
|
+
*/
|
|
202
|
+
_setEnabledState(requestedEnabledState) {
|
|
203
|
+
(0, node_opcua_assert_1.assert)(typeof requestedEnabledState === "boolean");
|
|
204
|
+
const enabledState = this.getEnabledState();
|
|
205
|
+
if (enabledState && requestedEnabledState) {
|
|
206
|
+
return node_opcua_status_code_1.StatusCodes.BadConditionAlreadyEnabled;
|
|
207
|
+
}
|
|
208
|
+
if (!enabledState && !requestedEnabledState) {
|
|
209
|
+
return node_opcua_status_code_1.StatusCodes.BadConditionAlreadyDisabled;
|
|
210
|
+
}
|
|
211
|
+
this._branch0.setEnabledState(requestedEnabledState);
|
|
212
|
+
// conditionNode.enabledState.setValue(requestedEnabledState);
|
|
213
|
+
// xx assert(conditionNode.enabledState.id.readValue().value.value === requestedEnabledState,"sanity check 1");
|
|
214
|
+
// xx assert(conditionNode.currentBranch().getEnabledState() === requestedEnabledState,"sanity check 2");
|
|
215
|
+
if (!requestedEnabledState) {
|
|
216
|
+
// as per Spec 1.0.3 part 9:
|
|
217
|
+
// * When the Condition instance enters the Disabled state, the Retain Property of this
|
|
218
|
+
// Condition shall be set to FALSE by the Server to indicate to the Client that the
|
|
219
|
+
// Condition instance is currently not of interest to Clients.
|
|
220
|
+
// TODO : shall we really set retain to false or artificially expose the retain false as false
|
|
221
|
+
// whist enabled state is false ?
|
|
222
|
+
this._previousRetainFlag = this.currentBranch().getRetain();
|
|
223
|
+
this.currentBranch().setRetain(false);
|
|
224
|
+
// todo: install the mechanism by which all condition values will be return
|
|
225
|
+
// as Null | BadConditionDisabled;
|
|
226
|
+
const statusCode = node_opcua_status_code_1.StatusCodes.BadConditionDisabled;
|
|
227
|
+
// a notification must be send
|
|
228
|
+
this.raiseConditionEvent(this.currentBranch(), true);
|
|
229
|
+
}
|
|
230
|
+
else {
|
|
231
|
+
// * When the Condition instance enters the enabled state, the Condition shall be
|
|
232
|
+
// evaluated and all of its Properties updated to reflect the current values. If this
|
|
233
|
+
// evaluation causes the Retain Property to transition to TRUE for any ConditionBranch,
|
|
234
|
+
// then an Event Notification shall be generated for that ConditionBranch.
|
|
235
|
+
this.evaluateConditionsAfterEnabled();
|
|
236
|
+
// todo evaluate branches
|
|
237
|
+
// conditionNode.evaluateBranches();
|
|
238
|
+
// restore retain flag
|
|
239
|
+
if (Object.prototype.hasOwnProperty.call(this, "_previousRetainFlag")) {
|
|
240
|
+
this.currentBranch().setRetain(this._previousRetainFlag);
|
|
241
|
+
}
|
|
242
|
+
// todo send notification for branches with retain = true
|
|
243
|
+
let nb_condition_resent = 0;
|
|
244
|
+
if (this.currentBranch().getRetain()) {
|
|
245
|
+
nb_condition_resent += this._resend_conditionEvents();
|
|
246
|
+
}
|
|
247
|
+
if (nb_condition_resent === 0) {
|
|
248
|
+
// a notification must be send
|
|
249
|
+
this.raiseConditionEvent(this.currentBranch(), true);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
return node_opcua_status_code_1.StatusCodes.Good;
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
*
|
|
256
|
+
* @method setEnabledState
|
|
257
|
+
* @param requestedEnabledState {Boolean}
|
|
258
|
+
* @private
|
|
259
|
+
*/
|
|
260
|
+
setEnabledState(requestedEnabledState) {
|
|
261
|
+
return this._setEnabledState(requestedEnabledState);
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* @method setReceiveTime
|
|
265
|
+
* @param time {Date}
|
|
266
|
+
*/
|
|
267
|
+
setReceiveTime(time) {
|
|
268
|
+
return this._branch0.setReceiveTime(time);
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* @method setLocalTime (optional)
|
|
272
|
+
* @param time
|
|
273
|
+
*/
|
|
274
|
+
setLocalTime(time) {
|
|
275
|
+
return this._branch0.setLocalTime(time);
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* @method setTime
|
|
279
|
+
* @param time {Date}
|
|
280
|
+
*/
|
|
281
|
+
setTime(time) {
|
|
282
|
+
return this._branch0.setTime(time);
|
|
283
|
+
}
|
|
284
|
+
_assert_valid() {
|
|
285
|
+
(0, node_opcua_assert_1.assert)(this.receiveTime.readValue().value.dataType === node_opcua_variant_1.DataType.DateTime);
|
|
286
|
+
(0, node_opcua_assert_1.assert)(this.receiveTime.readValue().value.value instanceof Date);
|
|
287
|
+
(0, node_opcua_assert_1.assert)(this.message.readValue().value.dataType === node_opcua_variant_1.DataType.LocalizedText);
|
|
288
|
+
(0, node_opcua_assert_1.assert)(this.severity.readValue().value.dataType === node_opcua_variant_1.DataType.UInt16);
|
|
289
|
+
(0, node_opcua_assert_1.assert)(this.time.readValue().value.dataType === node_opcua_variant_1.DataType.DateTime);
|
|
290
|
+
(0, node_opcua_assert_1.assert)(this.time.readValue().value.value instanceof Date);
|
|
291
|
+
(0, node_opcua_assert_1.assert)(this.quality.readValue().value.dataType === node_opcua_variant_1.DataType.StatusCode);
|
|
292
|
+
(0, node_opcua_assert_1.assert)(this.enabledState.readValue().value.dataType === node_opcua_variant_1.DataType.LocalizedText);
|
|
293
|
+
(0, node_opcua_assert_1.assert)(this.branchId.readValue().value.dataType === node_opcua_variant_1.DataType.NodeId);
|
|
294
|
+
// note localTime has been made optional in 1.04
|
|
295
|
+
(0, node_opcua_assert_1.assert)(!this.localTime || this.localTime.readValue().value.dataType === node_opcua_variant_1.DataType.ExtensionObject);
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* @method conditionOfNode
|
|
299
|
+
* @return {UAObject}
|
|
300
|
+
*/
|
|
301
|
+
conditionOfNode() {
|
|
302
|
+
const refs = this.findReferencesExAsObject("HasCondition", node_opcua_data_model_1.BrowseDirection.Inverse);
|
|
303
|
+
if (refs.length === 0) {
|
|
304
|
+
return null;
|
|
305
|
+
}
|
|
306
|
+
(0, node_opcua_assert_1.assert)(refs.length !== 0, "UACondition must be the condition of some node");
|
|
307
|
+
(0, node_opcua_assert_1.assert)(refs.length === 1, "expecting only one ConditionOf");
|
|
308
|
+
const node = refs[0];
|
|
309
|
+
(0, node_opcua_assert_1.assert)(node.nodeClass === node_opcua_data_model_1.NodeClass.Object || node.nodeClass === node_opcua_data_model_1.NodeClass.Variable, "node for which we are the condition shall be an UAObject or UAVariable");
|
|
310
|
+
return node;
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* @method raiseConditionEvent
|
|
314
|
+
* Raise a Instance Event
|
|
315
|
+
* (see also UAObject#raiseEvent to raise a transient event)
|
|
316
|
+
* @param branch the condition branch to raise
|
|
317
|
+
* @param renewEventId true if event Id of the condition branch should be renewed
|
|
318
|
+
*/
|
|
319
|
+
raiseConditionEvent(branch, renewEventId) {
|
|
320
|
+
(0, node_opcua_assert_1.assert)(arguments.length === 2, "expecting 2 arguments");
|
|
321
|
+
if (renewEventId) {
|
|
322
|
+
branch.renewEventId();
|
|
323
|
+
}
|
|
324
|
+
// xx console.log("MMMMMMMM%%%%%%%%%%%%%%%%%%%%% branch " +
|
|
325
|
+
// branch.getBranchId().toString() + " eventId = " + branch.getEventId().toString("hex"));
|
|
326
|
+
(0, node_opcua_assert_1.assert)(branch instanceof condition_snapshot_impl_1.ConditionSnapshotImpl);
|
|
327
|
+
this._assert_valid();
|
|
328
|
+
// In fact the event is raised by the object of which we are the condition
|
|
329
|
+
const conditionOfNode = this.conditionOfNode();
|
|
330
|
+
if (conditionOfNode) {
|
|
331
|
+
const eventData = branch._constructEventData();
|
|
332
|
+
this.emit("event", eventData);
|
|
333
|
+
if (conditionOfNode instanceof ua_object_impl_1.UAObjectImpl) {
|
|
334
|
+
// xx assert(conditionOfNode.eventNotifier === 0x01);
|
|
335
|
+
conditionOfNode._bubble_up_event(eventData);
|
|
336
|
+
}
|
|
337
|
+
else {
|
|
338
|
+
(0, node_opcua_assert_1.assert)(conditionOfNode.nodeClass === node_opcua_data_model_1.NodeClass.Variable);
|
|
339
|
+
// in this case
|
|
340
|
+
const eventOfs = conditionOfNode.getEventSourceOfs();
|
|
341
|
+
(0, node_opcua_assert_1.assert)(eventOfs.length === 1);
|
|
342
|
+
const node = eventOfs[0];
|
|
343
|
+
if (node instanceof ua_object_impl_1.UAObjectImpl) {
|
|
344
|
+
node._bubble_up_event(eventData);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
else {
|
|
349
|
+
warningLog("Condition ", this.nodeId.toString(), "is not linked to a Object with a IsConditionOf(reversed(HasCondition))");
|
|
350
|
+
}
|
|
351
|
+
// xx console.log("MMMMMMMM%%%%%%%%%%%%%%%%%%%%% branch " +
|
|
352
|
+
// branch.getBranchId().toString() + " eventId = " + branch.getEventId().toString("hex"));
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
*
|
|
356
|
+
* @method raiseNewCondition
|
|
357
|
+
* @param conditionInfo {ConditionInfo}
|
|
358
|
+
*
|
|
359
|
+
*/
|
|
360
|
+
raiseNewCondition(conditionInfo) {
|
|
361
|
+
if (!this.getEnabledState()) {
|
|
362
|
+
throw new Error("UACondition#raiseNewCondition Condition is not enabled");
|
|
363
|
+
}
|
|
364
|
+
conditionInfo = conditionInfo || {};
|
|
365
|
+
conditionInfo.severity = Object.prototype.hasOwnProperty.call(conditionInfo, "severity")
|
|
366
|
+
? conditionInfo.severity
|
|
367
|
+
: UAConditionImpl.defaultSeverity;
|
|
368
|
+
// only valid for ConditionObjects
|
|
369
|
+
// todo check that object is of type ConditionType
|
|
370
|
+
const addressSpace = this.addressSpace;
|
|
371
|
+
const selfConditionType = this.typeDefinitionObj;
|
|
372
|
+
const conditionType = addressSpace.findObjectType("ConditionType");
|
|
373
|
+
(0, node_opcua_assert_1.assert)(selfConditionType.isSupertypeOf(conditionType));
|
|
374
|
+
const branch = this.currentBranch();
|
|
375
|
+
const now = new Date();
|
|
376
|
+
// install the eventTimestamp
|
|
377
|
+
// set the received Time
|
|
378
|
+
branch.setTime(now);
|
|
379
|
+
branch.setReceiveTime(now);
|
|
380
|
+
// note : in 1.04 LocalTime property is optional
|
|
381
|
+
if (Object.prototype.hasOwnProperty.call(this, "localTime")) {
|
|
382
|
+
branch.setLocalTime(new node_opcua_types_1.TimeZoneDataType({
|
|
383
|
+
daylightSavingInOffset: false,
|
|
384
|
+
offset: 0
|
|
385
|
+
}));
|
|
386
|
+
}
|
|
387
|
+
if (Object.prototype.hasOwnProperty.call(conditionInfo, "message") && conditionInfo.message) {
|
|
388
|
+
branch.setMessage(conditionInfo.message);
|
|
389
|
+
}
|
|
390
|
+
// todo receive time : when the server received the event from the underlying system.
|
|
391
|
+
// self.receiveTime.setValueFromSource();
|
|
392
|
+
if (Object.prototype.hasOwnProperty.call(conditionInfo, "severity") && conditionInfo.severity !== null) {
|
|
393
|
+
(0, node_opcua_assert_1.assert)(isFinite(conditionInfo.severity));
|
|
394
|
+
branch.setSeverity(conditionInfo.severity);
|
|
395
|
+
}
|
|
396
|
+
if (Object.prototype.hasOwnProperty.call(conditionInfo, "quality") && conditionInfo.quality !== null) {
|
|
397
|
+
(0, node_opcua_assert_1.assert)(conditionInfo.quality instanceof node_opcua_status_code_1.StatusCode);
|
|
398
|
+
branch.setQuality(conditionInfo.quality);
|
|
399
|
+
}
|
|
400
|
+
if (Object.prototype.hasOwnProperty.call(conditionInfo, "retain") && conditionInfo.retain !== null) {
|
|
401
|
+
(0, node_opcua_assert_1.assert)(typeof conditionInfo.retain === "boolean");
|
|
402
|
+
branch.setRetain(!!conditionInfo.retain);
|
|
403
|
+
}
|
|
404
|
+
this.raiseConditionEvent(branch, true);
|
|
405
|
+
}
|
|
406
|
+
raiseNewBranchState(branch) {
|
|
407
|
+
this.raiseConditionEvent(branch, true);
|
|
408
|
+
if (!(0, node_opcua_nodeid_1.sameNodeId)(branch.getBranchId(), node_opcua_nodeid_1.NodeId.nullNodeId) && !branch.getRetain()) {
|
|
409
|
+
// xx console.log(" Deleting not longer needed branch ", branch.getBranchId().toString());
|
|
410
|
+
// branch can be deleted
|
|
411
|
+
this.deleteBranch(branch);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
/**
|
|
415
|
+
* @method currentBranch
|
|
416
|
+
* @return {ConditionSnapshot}
|
|
417
|
+
*/
|
|
418
|
+
currentBranch() {
|
|
419
|
+
return this._branch0;
|
|
420
|
+
}
|
|
421
|
+
_resend_conditionEvents() {
|
|
422
|
+
// for the time being , only current branch
|
|
423
|
+
const currentBranch = this.currentBranch();
|
|
424
|
+
if (currentBranch.getRetain()) {
|
|
425
|
+
debugLog(" resending condition event for " + this.browseName.toString());
|
|
426
|
+
this.raiseConditionEvent(currentBranch, false);
|
|
427
|
+
return 1;
|
|
428
|
+
}
|
|
429
|
+
return 0;
|
|
430
|
+
}
|
|
431
|
+
// ------------------------------------------------------------------------------------
|
|
432
|
+
// Acknowledgeable
|
|
433
|
+
// ------------------------------------------------------------------------------------
|
|
434
|
+
/**
|
|
435
|
+
* @method _raiseAuditConditionCommentEvent
|
|
436
|
+
* @param sourceName {string}
|
|
437
|
+
* @param conditionEventId {Buffer}
|
|
438
|
+
* @param comment {LocalizedText}
|
|
439
|
+
* @private
|
|
440
|
+
*/
|
|
441
|
+
_raiseAuditConditionCommentEvent(sourceName, conditionEventId, comment) {
|
|
442
|
+
(0, node_opcua_assert_1.assert)(conditionEventId === null || conditionEventId instanceof Buffer);
|
|
443
|
+
(0, node_opcua_assert_1.assert)(comment instanceof node_opcua_data_model_1.LocalizedText);
|
|
444
|
+
const server = this.addressSpace.rootFolder.objects.server;
|
|
445
|
+
const now = new Date();
|
|
446
|
+
// xx if (true || server.isAuditing) {
|
|
447
|
+
// ----------------------------------------------------------------------------------------------------
|
|
448
|
+
server.raiseEvent("AuditConditionCommentEventType", {
|
|
449
|
+
// AuditEventType
|
|
450
|
+
/* part 5 - 6.4.3 AuditEventType */
|
|
451
|
+
actionTimeStamp: {
|
|
452
|
+
dataType: "DateTime",
|
|
453
|
+
value: now
|
|
454
|
+
},
|
|
455
|
+
status: {
|
|
456
|
+
dataType: "Boolean",
|
|
457
|
+
value: true
|
|
458
|
+
},
|
|
459
|
+
serverId: {
|
|
460
|
+
dataType: "String",
|
|
461
|
+
value: ""
|
|
462
|
+
},
|
|
463
|
+
// ClientAuditEntryId contains the human-readable AuditEntryId defined in Part 3.
|
|
464
|
+
clientAuditEntryId: {
|
|
465
|
+
dataType: "String",
|
|
466
|
+
value: ""
|
|
467
|
+
},
|
|
468
|
+
// The ClientUserId identifies the user of the client requesting an action. The ClientUserId can be
|
|
469
|
+
// obtained from the UserIdentityToken passed in the ActivateSession call.
|
|
470
|
+
clientUserId: {
|
|
471
|
+
dataType: "String",
|
|
472
|
+
value: ""
|
|
473
|
+
},
|
|
474
|
+
sourceName: {
|
|
475
|
+
dataType: "String",
|
|
476
|
+
value: sourceName
|
|
477
|
+
},
|
|
478
|
+
// AuditUpdateMethodEventType
|
|
479
|
+
methodId: {
|
|
480
|
+
dataType: "Null"
|
|
481
|
+
},
|
|
482
|
+
inputArguments: {
|
|
483
|
+
dataType: "Null"
|
|
484
|
+
},
|
|
485
|
+
// AuditConditionCommentEventType
|
|
486
|
+
conditionEventId: {
|
|
487
|
+
dataType: "ByteString",
|
|
488
|
+
value: conditionEventId
|
|
489
|
+
},
|
|
490
|
+
comment: {
|
|
491
|
+
dataType: "LocalizedText",
|
|
492
|
+
value: comment
|
|
493
|
+
}
|
|
494
|
+
});
|
|
495
|
+
// xx }
|
|
496
|
+
}
|
|
497
|
+
_findBranchForEventId(eventId) {
|
|
498
|
+
if (sameBuffer(this.eventId.readValue().value.value, eventId)) {
|
|
499
|
+
return this.currentBranch();
|
|
500
|
+
}
|
|
501
|
+
const e = Object.values(this._branches).filter((branch) => sameBuffer(branch.getEventId(), eventId));
|
|
502
|
+
if (e.length === 1) {
|
|
503
|
+
return e[0];
|
|
504
|
+
}
|
|
505
|
+
(0, node_opcua_assert_1.assert)(e.length === 0, "cannot have 2 branches with same eventId");
|
|
506
|
+
return null; // not found
|
|
507
|
+
}
|
|
508
|
+
evaluateConditionsAfterEnabled() {
|
|
509
|
+
(0, node_opcua_assert_1.assert)(this.getEnabledState() === true);
|
|
510
|
+
throw new Error("Unimplemented , please override");
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
exports.UAConditionImpl = UAConditionImpl;
|
|
514
|
+
UAConditionImpl.defaultSeverity = 250;
|
|
515
|
+
UAConditionImpl.typeDefinition = (0, node_opcua_nodeid_1.resolveNodeId)("ConditionType");
|
|
516
|
+
/**
|
|
517
|
+
* instantiate a Condition.
|
|
518
|
+
* this will create the unique EventId and will set eventType
|
|
519
|
+
* @method instantiate
|
|
520
|
+
* @param namespace {INamespace}
|
|
521
|
+
* @param conditionTypeId {String|NodeId} the EventType to instantiate
|
|
522
|
+
* @param options {object}
|
|
523
|
+
* @param options.browseName {String|QualifiedName}
|
|
524
|
+
* @param options.componentOf {NodeId|UAObject}
|
|
525
|
+
* @param options.conditionOf {NodeId|UAObject} Mandatory
|
|
526
|
+
* @param options.organizedBy {NodeId|UAObject} ( only provide componentOf or organizedBy but not both)
|
|
527
|
+
* @param [options.conditionClass =BaseConditionClassType] {NodeId|UAObject}
|
|
528
|
+
* The condition Class nodeId or object used to set the ConditionClassId and
|
|
529
|
+
* ConditionClassName properties of the condition.
|
|
530
|
+
*
|
|
531
|
+
* @param options.conditionSource {NodeId|UAObject} the condition source node.
|
|
532
|
+
* this node must be marked a EventSource.
|
|
533
|
+
* the conditionSource is used to populate the sourceNode and
|
|
534
|
+
* sourceName variables defined by BaseEventType
|
|
535
|
+
* @param options.conditionName {String} the condition Name
|
|
536
|
+
* @param [options.optionals] [Array<String>] an Array of optionals fields
|
|
537
|
+
*
|
|
538
|
+
* @param data a object containing the value to set
|
|
539
|
+
* @param data.eventId {String|NodeId} the EventType Identifier to instantiate (type cannot be abstract)
|
|
540
|
+
* @return a instantiated UAConditionEx
|
|
541
|
+
*/
|
|
542
|
+
function UACondition_instantiate(namespace, conditionTypeId, options, data) {
|
|
543
|
+
/* eslint max-statements: ["error", 100] */
|
|
544
|
+
const addressSpace = namespace.addressSpace;
|
|
545
|
+
const conditionType = addressSpace.findEventType(conditionTypeId);
|
|
546
|
+
/* istanbul ignore next */
|
|
547
|
+
if (!conditionType) {
|
|
548
|
+
throw new Error(" cannot find Condition Type for " + conditionTypeId);
|
|
549
|
+
}
|
|
550
|
+
// reminder : abstract event type cannot be instantiated directly !
|
|
551
|
+
(0, node_opcua_assert_1.assert)(!conditionType.isAbstract, "Cannot instantiate abstract conditionType");
|
|
552
|
+
const baseConditionEventType = addressSpace.findEventType("ConditionType");
|
|
553
|
+
/* istanbul ignore next */
|
|
554
|
+
if (!baseConditionEventType) {
|
|
555
|
+
throw new Error("cannot find ConditionType");
|
|
556
|
+
}
|
|
557
|
+
(0, node_opcua_assert_1.assert)(conditionType.isSupertypeOf(baseConditionEventType));
|
|
558
|
+
// assert((typeof options.browseName === "string"));
|
|
559
|
+
options.browseName = options.browseName || "??? instantiateCondition - missing browseName";
|
|
560
|
+
options.optionals = options.optionals || [];
|
|
561
|
+
// now optionals in 1.04
|
|
562
|
+
options.optionals.push("EventType");
|
|
563
|
+
options.optionals.push("BranchId");
|
|
564
|
+
//
|
|
565
|
+
options.optionals.push("Comment");
|
|
566
|
+
options.optionals.push("Comment.SourceTimestamp");
|
|
567
|
+
options.optionals.push("EnabledState.TrueState");
|
|
568
|
+
options.optionals.push("EnabledState.TrueState");
|
|
569
|
+
options.optionals.push("EnabledState.FalseState");
|
|
570
|
+
options.optionals.push("EnabledState.TransitionTime");
|
|
571
|
+
options.optionals.push("EnabledState.EffectiveTransitionTime");
|
|
572
|
+
options.optionals.push("EnabledState.EffectiveDisplayName");
|
|
573
|
+
const conditionNode = conditionType.instantiate(options);
|
|
574
|
+
Object.setPrototypeOf(conditionNode, UAConditionImpl.prototype);
|
|
575
|
+
conditionNode.initialize();
|
|
576
|
+
(0, node_opcua_assert_1.assert)(Object.prototype.hasOwnProperty.call(options, "conditionSource"), "must specify a condition source either as null or as a UAObject");
|
|
577
|
+
if (!options.conditionOf) {
|
|
578
|
+
options.conditionOf = options.conditionSource;
|
|
579
|
+
}
|
|
580
|
+
if (options.conditionOf) {
|
|
581
|
+
(0, node_opcua_assert_1.assert)(Object.prototype.hasOwnProperty.call(options, "conditionOf")); // must provide a conditionOf
|
|
582
|
+
options.conditionOf = addressSpace._coerceNode(options.conditionOf);
|
|
583
|
+
// HasCondition References can be used in the Type definition of an Object or a Variable.
|
|
584
|
+
(0, node_opcua_assert_1.assert)(options.conditionOf.nodeClass === node_opcua_data_model_1.NodeClass.Object || options.conditionOf.nodeClass === node_opcua_data_model_1.NodeClass.Variable);
|
|
585
|
+
conditionNode.addReference({
|
|
586
|
+
isForward: false,
|
|
587
|
+
nodeId: options.conditionOf,
|
|
588
|
+
referenceType: "HasCondition"
|
|
589
|
+
});
|
|
590
|
+
(0, node_opcua_assert_1.assert)(conditionNode.conditionOfNode().nodeId === options.conditionOf.nodeId);
|
|
591
|
+
}
|
|
592
|
+
// the constant property of this condition
|
|
593
|
+
conditionNode.eventType.setValueFromSource({
|
|
594
|
+
dataType: node_opcua_variant_1.DataType.NodeId,
|
|
595
|
+
value: conditionType.nodeId
|
|
596
|
+
});
|
|
597
|
+
data = data || {};
|
|
598
|
+
// install initial branch ID (null NodeId);
|
|
599
|
+
conditionNode.branchId.setValueFromSource({
|
|
600
|
+
dataType: node_opcua_variant_1.DataType.NodeId,
|
|
601
|
+
value: new node_opcua_nodeid_1.NodeId()
|
|
602
|
+
});
|
|
603
|
+
// install 'Comment' condition variable
|
|
604
|
+
_install_condition_variable_type(conditionNode.comment);
|
|
605
|
+
// install 'Quality' condition variable
|
|
606
|
+
_install_condition_variable_type(conditionNode.quality);
|
|
607
|
+
// xx conditionNode.quality.setValueFromSource({dataType: DataType.StatusCode,value: StatusCodes.Good });
|
|
608
|
+
// install 'LastSeverity' condition variable
|
|
609
|
+
_install_condition_variable_type(conditionNode.lastSeverity);
|
|
610
|
+
// xx conditionNode.severity.setValueFromSource({dataType: DataType.UInt16,value: 0 });
|
|
611
|
+
// xx conditionNode.lastSeverity.setValueFromSource({dataType: DataType.UInt16,value: 0 });
|
|
612
|
+
// install 'EnabledState' TwoStateVariable
|
|
613
|
+
/**
|
|
614
|
+
* @property enabledState
|
|
615
|
+
* @type {UATwoStateVariable}
|
|
616
|
+
*/
|
|
617
|
+
// -------------- fixing missing EnabledState.EffectiveDisplayName
|
|
618
|
+
if (!conditionNode.enabledState.effectiveDisplayName) {
|
|
619
|
+
namespace.addVariable({
|
|
620
|
+
browseName: new node_opcua_data_model_1.QualifiedName({ namespaceIndex: 0, name: "EffectiveDisplayName" }),
|
|
621
|
+
dataType: "LocalizedText",
|
|
622
|
+
propertyOf: conditionNode.enabledState
|
|
623
|
+
});
|
|
624
|
+
}
|
|
625
|
+
(0, ua_two_state_variable_1._install_TwoStateVariable_machinery)(conditionNode.enabledState, {
|
|
626
|
+
falseState: "Disabled",
|
|
627
|
+
trueState: "Enabled"
|
|
628
|
+
});
|
|
629
|
+
// installing sourceName and sourceNode
|
|
630
|
+
conditionNode.enabledState.setValue(true);
|
|
631
|
+
// set properties to in initial values
|
|
632
|
+
Object.entries(data).forEach(([key, value]) => {
|
|
633
|
+
const varNode = _getCompositeKey(conditionNode, key);
|
|
634
|
+
(0, node_opcua_assert_1.assert)(varNode.nodeClass === node_opcua_data_model_1.NodeClass.Variable);
|
|
635
|
+
const variant = new node_opcua_variant_1.Variant(value);
|
|
636
|
+
// check that Variant DataType is compatible with the UAVariable dataType
|
|
637
|
+
// xx var nodeDataType = addressSpace.findNode(varNode.dataType).browseName;
|
|
638
|
+
/* istanbul ignore next */
|
|
639
|
+
if (!varNode._validate_DataType(variant.dataType)) {
|
|
640
|
+
throw new Error(" Invalid variant dataType " + variant + " " + varNode.browseName.toString());
|
|
641
|
+
}
|
|
642
|
+
varNode.setValueFromSource(variant);
|
|
643
|
+
});
|
|
644
|
+
// bind condition methods -
|
|
645
|
+
/**
|
|
646
|
+
* @property enable
|
|
647
|
+
* @type {UAMethod}
|
|
648
|
+
*/
|
|
649
|
+
conditionNode.enable.bindMethod(_enable_method);
|
|
650
|
+
/**
|
|
651
|
+
* @property disable
|
|
652
|
+
* @type {UAMethod}
|
|
653
|
+
*/
|
|
654
|
+
conditionNode.disable.bindMethod(_disable_method);
|
|
655
|
+
// bind condition methods - AddComment
|
|
656
|
+
/**
|
|
657
|
+
* @property addComment
|
|
658
|
+
* @type {UAMethod}
|
|
659
|
+
*/
|
|
660
|
+
conditionNode.addComment.bindMethod(_add_comment_method);
|
|
661
|
+
(0, node_opcua_assert_1.assert)(conditionNode instanceof UAConditionImpl);
|
|
662
|
+
// ConditionSource => cf SourceNode
|
|
663
|
+
// As per spec OPCUA 1.03 part 9 page 54:
|
|
664
|
+
// The ConditionType inherits all Properties of the BaseEventType. Their semantic is defined in
|
|
665
|
+
// Part 5. SourceNode identifies the ConditionSource.
|
|
666
|
+
// The SourceNode is the Node which the condition is associated with, it may be the same as the
|
|
667
|
+
// InputNode for an alarm, but it may be a separate node. For example a motor, which is a
|
|
668
|
+
// variable with a value that is an RPM, may be the ConditionSource for Conditions that are
|
|
669
|
+
// related to the motor as well as a temperature sensor associated with the motor. In the former
|
|
670
|
+
// the InputNode for the High RPM alarm is the value of the Motor RPM, while in the later the
|
|
671
|
+
// InputNode of the High Alarm would be the value of the temperature sensor that is associated
|
|
672
|
+
// with the motor.
|
|
673
|
+
if (options.conditionSource) {
|
|
674
|
+
options.conditionSource = addressSpace._coerceNode(options.conditionSource);
|
|
675
|
+
if (options.conditionSource.nodeClass !== node_opcua_data_model_1.NodeClass.Object && options.conditionSource.nodeClass !== node_opcua_data_model_1.NodeClass.Variable) {
|
|
676
|
+
// tslint:disable:no-console
|
|
677
|
+
console.log(options.conditionSource);
|
|
678
|
+
throw new Error("Expecting condition source to be NodeClass.Object or Variable");
|
|
679
|
+
}
|
|
680
|
+
const conditionSourceNode = addressSpace.findNode(options.conditionSource.nodeId);
|
|
681
|
+
if (conditionSourceNode) {
|
|
682
|
+
conditionNode.sourceNode.setValueFromSource({
|
|
683
|
+
dataType: node_opcua_variant_1.DataType.NodeId,
|
|
684
|
+
value: conditionSourceNode.nodeId
|
|
685
|
+
});
|
|
686
|
+
// conditionSourceNode node must be registered as a EventSource of an other node.
|
|
687
|
+
// As per spec OPCUA 1.03 part 9 page 54:
|
|
688
|
+
// HasNotifier and HasEventSource References are used to expose the hierarchical organization
|
|
689
|
+
// of Event notifying Objects and ConditionSources. An Event notifying Object represents
|
|
690
|
+
// typically an area of Operator responsibility. The definition of such an area configuration is
|
|
691
|
+
// outside the scope of this standard. If areas are available they shall be linked together and
|
|
692
|
+
// with the included ConditionSources using the HasNotifier and the HasEventSource Reference
|
|
693
|
+
// Types. The Server Object shall be the root of this hierarchy.
|
|
694
|
+
if (!(0, node_opcua_nodeid_1.sameNodeId)(conditionSourceNode.nodeId, (0, node_opcua_nodeid_1.coerceNodeId)("ns=0;i=2253"))) {
|
|
695
|
+
// server object
|
|
696
|
+
/* istanbul ignore next */
|
|
697
|
+
if (conditionSourceNode.getEventSourceOfs().length === 0) {
|
|
698
|
+
errorLog("conditionSourceNode = ", conditionSourceNode.browseName.toString());
|
|
699
|
+
errorLog("conditionSourceNode = ", conditionSourceNode.nodeId.toString());
|
|
700
|
+
throw new Error("conditionSourceNode must be an event source " +
|
|
701
|
+
conditionSourceNode.browseName.toString() +
|
|
702
|
+
conditionSourceNode.nodeId.toString());
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
// set source Node (defined in UABaseEventType)
|
|
706
|
+
conditionNode.sourceNode.setValueFromSource(conditionSourceNode.readAttribute(null, node_opcua_data_model_1.AttributeIds.NodeId).value);
|
|
707
|
+
// set source Name (defined in UABaseEventType)
|
|
708
|
+
const displayName = conditionSourceNode.readAttribute(null, node_opcua_data_model_1.AttributeIds.DisplayName).value
|
|
709
|
+
.value;
|
|
710
|
+
conditionNode.sourceName.setValueFromSource({ dataType: node_opcua_variant_1.DataType.String, value: displayName.text });
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
conditionNode.eventType.setValueFromSource({
|
|
714
|
+
dataType: node_opcua_variant_1.DataType.NodeId,
|
|
715
|
+
value: conditionType.nodeId
|
|
716
|
+
});
|
|
717
|
+
// as per spec:
|
|
718
|
+
/**
|
|
719
|
+
*
|
|
720
|
+
* dataType: DataType.NodeId
|
|
721
|
+
*
|
|
722
|
+
* As per spec OPCUA 1.03 part 9:
|
|
723
|
+
* ConditionClassId specifies in which domain this Condition is used. It is the NodeId of the
|
|
724
|
+
* corresponding ConditionClassType. See 5.9 for the definition of ConditionClass and a set of
|
|
725
|
+
* ConditionClasses defined in this standard. When using this Property for filtering, Clients have
|
|
726
|
+
* to specify all individual ConditionClassType NodeIds. The OfType operator cannot be applied.
|
|
727
|
+
* BaseConditionClassType is used as class whenever a Condition cannot be assigned to a
|
|
728
|
+
* more concrete class.
|
|
729
|
+
*
|
|
730
|
+
* BaseConditionClassType
|
|
731
|
+
* |
|
|
732
|
+
* +---------------------------+----------------------------+
|
|
733
|
+
* | | |
|
|
734
|
+
* ProcessConditionClassType MaintenanceConditionClassType SystemConditionClassType
|
|
735
|
+
*
|
|
736
|
+
* @property conditionName
|
|
737
|
+
* @type {UAVariable}
|
|
738
|
+
*/
|
|
739
|
+
const baseConditionClassType = addressSpace.findObjectType("ProcessConditionClassType");
|
|
740
|
+
// assert(baseConditionClassType,"Expecting BaseConditionClassType to be in addressSpace");
|
|
741
|
+
let conditionClassId = baseConditionClassType ? baseConditionClassType.nodeId : new node_opcua_nodeid_1.NodeId();
|
|
742
|
+
let conditionClassName = baseConditionClassType ? baseConditionClassType.displayName[0] : "";
|
|
743
|
+
if (options.conditionClass) {
|
|
744
|
+
if (typeof options.conditionClass === "string") {
|
|
745
|
+
options.conditionClass = addressSpace.findObjectType(options.conditionClass);
|
|
746
|
+
if (!options.conditionClass) {
|
|
747
|
+
throw new Error("cannot find condition class " + options.conditionClass);
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
const conditionClassNode = addressSpace._coerceNode(options.conditionClass);
|
|
751
|
+
if (!conditionClassNode) {
|
|
752
|
+
throw new Error("cannot find condition class " + options.conditionClass.toString());
|
|
753
|
+
}
|
|
754
|
+
conditionClassId = conditionClassNode.nodeId;
|
|
755
|
+
conditionClassName = conditionClassNode.displayName[0];
|
|
756
|
+
}
|
|
757
|
+
conditionNode.conditionClassId.setValueFromSource({
|
|
758
|
+
dataType: node_opcua_variant_1.DataType.NodeId,
|
|
759
|
+
value: conditionClassId
|
|
760
|
+
});
|
|
761
|
+
// as per spec:
|
|
762
|
+
// ConditionClassName provides the display name of the ConditionClassType.
|
|
763
|
+
conditionNode.conditionClassName.setValueFromSource({
|
|
764
|
+
dataType: node_opcua_variant_1.DataType.LocalizedText,
|
|
765
|
+
value: (0, node_opcua_data_model_1.coerceLocalizedText)(conditionClassName)
|
|
766
|
+
});
|
|
767
|
+
// as per spec:
|
|
768
|
+
/**
|
|
769
|
+
*
|
|
770
|
+
* dataType: DataType.String
|
|
771
|
+
*
|
|
772
|
+
* As per spec OPCUA 1.03 part 9:
|
|
773
|
+
* ConditionName identifies the Condition instance that the Event originated from. It can be used
|
|
774
|
+
* together with the SourceName in a user display to distinguish between different Condition
|
|
775
|
+
* instances. If a ConditionSource has only one instance of a ConditionType, and the Server has
|
|
776
|
+
* no instance name, the Server shall supply the ConditionType browse name.
|
|
777
|
+
* @property conditionName
|
|
778
|
+
* @type {UAVariable}
|
|
779
|
+
*/
|
|
780
|
+
const conditionName = options.conditionName || "Unset Condition Name";
|
|
781
|
+
(0, node_opcua_assert_1.assert)(typeof conditionName === "string");
|
|
782
|
+
conditionNode.conditionName.setValueFromSource({
|
|
783
|
+
dataType: node_opcua_variant_1.DataType.String,
|
|
784
|
+
value: conditionName
|
|
785
|
+
});
|
|
786
|
+
// set SourceNode and SourceName based on HasCondition node
|
|
787
|
+
const sourceNodes = conditionNode.findReferencesAsObject("HasCondition", false);
|
|
788
|
+
if (sourceNodes.length) {
|
|
789
|
+
(0, node_opcua_assert_1.assert)(sourceNodes.length === 1);
|
|
790
|
+
conditionNode.setSourceNode(sourceNodes[0].nodeId);
|
|
791
|
+
conditionNode.setSourceName(sourceNodes[0].browseName.toString());
|
|
792
|
+
}
|
|
793
|
+
conditionNode.post_initialize();
|
|
794
|
+
const branch0 = conditionNode.currentBranch();
|
|
795
|
+
branch0.setRetain(false);
|
|
796
|
+
branch0.setComment("");
|
|
797
|
+
branch0.setQuality(node_opcua_status_code_1.StatusCodes.Good);
|
|
798
|
+
branch0.setSeverity(0);
|
|
799
|
+
branch0.setLocalTime(new node_opcua_types_1.TimeZoneDataType({
|
|
800
|
+
daylightSavingInOffset: false,
|
|
801
|
+
offset: 0
|
|
802
|
+
}));
|
|
803
|
+
branch0.setMessage("");
|
|
804
|
+
branch0.setReceiveTime(node_opcua_basic_types_2.minDate);
|
|
805
|
+
branch0.setTime(node_opcua_basic_types_2.minDate);
|
|
806
|
+
return conditionNode;
|
|
807
|
+
}
|
|
808
|
+
function _disable_method(inputArguments, context, callback) {
|
|
809
|
+
(0, node_opcua_assert_1.assert)(inputArguments.length === 0);
|
|
810
|
+
const conditionNode = context.object;
|
|
811
|
+
(0, node_opcua_assert_1.assert)(conditionNode);
|
|
812
|
+
// istanbul ignore next
|
|
813
|
+
if (!(conditionNode instanceof UAConditionImpl)) {
|
|
814
|
+
console.log("conditionNode is not a UACondition ", conditionNode === null || conditionNode === void 0 ? void 0 : conditionNode.toString());
|
|
815
|
+
return callback(null, {
|
|
816
|
+
statusCode: node_opcua_status_code_1.StatusCodes.BadNodeIdInvalid
|
|
817
|
+
});
|
|
818
|
+
}
|
|
819
|
+
const statusCode = conditionNode._setEnabledState(false);
|
|
820
|
+
return callback(null, {
|
|
821
|
+
statusCode
|
|
822
|
+
});
|
|
823
|
+
}
|
|
824
|
+
function _enable_method(inputArguments, context, callback) {
|
|
825
|
+
(0, node_opcua_assert_1.assert)(inputArguments.length === 0);
|
|
826
|
+
const conditionNode = context.object;
|
|
827
|
+
(0, node_opcua_assert_1.assert)(conditionNode);
|
|
828
|
+
if (!(conditionNode instanceof UAConditionImpl)) {
|
|
829
|
+
return callback(null, {
|
|
830
|
+
statusCode: node_opcua_status_code_1.StatusCodes.BadNodeIdInvalid
|
|
831
|
+
});
|
|
832
|
+
}
|
|
833
|
+
const statusCode = conditionNode._setEnabledState(true);
|
|
834
|
+
return callback(null, {
|
|
835
|
+
statusCode
|
|
836
|
+
});
|
|
837
|
+
}
|
|
838
|
+
function _condition_refresh_method(inputArguments, context, callback) {
|
|
839
|
+
// arguments : IntegerId SubscriptionId
|
|
840
|
+
(0, node_opcua_assert_1.assert)(inputArguments.length === 1);
|
|
841
|
+
const addressSpace = context.object.addressSpace;
|
|
842
|
+
if (doDebug) {
|
|
843
|
+
debugLog(chalk.red(" ConditionType.ConditionRefresh ! subscriptionId ="), inputArguments[0].toString());
|
|
844
|
+
}
|
|
845
|
+
const subscriptionId = inputArguments[0].value;
|
|
846
|
+
let statusCode = _check_subscription_id_is_valid(subscriptionId, context);
|
|
847
|
+
if (statusCode !== node_opcua_status_code_1.StatusCodes.Good) {
|
|
848
|
+
return statusCode;
|
|
849
|
+
}
|
|
850
|
+
statusCode = _perform_condition_refresh(addressSpace, inputArguments, context);
|
|
851
|
+
return callback(null, {
|
|
852
|
+
statusCode
|
|
853
|
+
});
|
|
854
|
+
}
|
|
855
|
+
function _perform_condition_refresh(addressSpace, inputArguments, context) {
|
|
856
|
+
// --- possible StatusCodes:
|
|
857
|
+
//
|
|
858
|
+
// Bad_SubscriptionIdInvalid See Part 4 for the description of this result code
|
|
859
|
+
// Bad_RefreshInProgress See Table 74 for the description of this result code
|
|
860
|
+
// Bad_UserAccessDenied The Method was not called in the context of the Session
|
|
861
|
+
// that owns the Subscription
|
|
862
|
+
//
|
|
863
|
+
// istanbul ignore next
|
|
864
|
+
if (addressSpace._condition_refresh_in_progress) {
|
|
865
|
+
// a refresh operation is already in progress....
|
|
866
|
+
return node_opcua_status_code_1.StatusCodes.BadRefreshInProgress;
|
|
867
|
+
}
|
|
868
|
+
addressSpace._condition_refresh_in_progress = true;
|
|
869
|
+
const server = context.object.addressSpace.rootFolder.objects.server;
|
|
870
|
+
const refreshStartEventType = addressSpace.findEventType("RefreshStartEventType");
|
|
871
|
+
const refreshEndEventType = addressSpace.findEventType("RefreshEndEventType");
|
|
872
|
+
server.raiseEvent(refreshStartEventType, {});
|
|
873
|
+
// todo : resend retained conditions
|
|
874
|
+
const _server = server;
|
|
875
|
+
// starting from server object ..
|
|
876
|
+
// evaluated all --> hasNotifier/hasEventSource -> node
|
|
877
|
+
_server._conditionRefresh();
|
|
878
|
+
server.raiseEvent(refreshEndEventType, {});
|
|
879
|
+
addressSpace._condition_refresh_in_progress = false;
|
|
880
|
+
return node_opcua_status_code_1.StatusCodes.Good;
|
|
881
|
+
}
|
|
882
|
+
function _condition_refresh2_method(inputArguments, context, callback) {
|
|
883
|
+
// arguments : IntegerId SubscriptionId
|
|
884
|
+
// arguments : IntegerId MonitoredItemId
|
|
885
|
+
(0, node_opcua_assert_1.assert)(inputArguments.length === 2);
|
|
886
|
+
if (!context.object) {
|
|
887
|
+
throw new Error("Invalid context => missing Object");
|
|
888
|
+
}
|
|
889
|
+
const addressSpace = context.object.addressSpace;
|
|
890
|
+
// istanbul ignore next
|
|
891
|
+
if (doDebug) {
|
|
892
|
+
debugLog(chalk.cyan.bgWhite(" ConditionType.conditionRefresh2 !"));
|
|
893
|
+
}
|
|
894
|
+
// xx var subscriptionId = inputArguments[0].value;
|
|
895
|
+
// xx var monitoredItemId = inputArguments[1].value;
|
|
896
|
+
const statusCode = _perform_condition_refresh(addressSpace, inputArguments, context);
|
|
897
|
+
return callback(null, {
|
|
898
|
+
statusCode
|
|
899
|
+
});
|
|
900
|
+
}
|
|
901
|
+
function _add_comment_method(inputArguments, context, callback) {
|
|
902
|
+
//
|
|
903
|
+
// The AddComment Method is used to apply a comment to a specific state of a Condition
|
|
904
|
+
// instance. Normally, the NodeId of the Object instance is passed as the ObjectId to the Call
|
|
905
|
+
// Service. However, some Servers do not expose Condition instances in the AddressSpace.
|
|
906
|
+
// Therefore, all Servers shall also allow Clients to call the AddComment Method by specifying
|
|
907
|
+
// ConditionId as the ObjectId. The Method cannot be called with an ObjectId of the
|
|
908
|
+
// ConditionType Node.
|
|
909
|
+
// Signature
|
|
910
|
+
// - EventId EventId identifying a particular Event Notification where a state was reported for a
|
|
911
|
+
// Condition.
|
|
912
|
+
// - Comment A localized text to be applied to the Condition.
|
|
913
|
+
//
|
|
914
|
+
// AlwaysGeneratesEvent AuditConditionCommentEventType
|
|
915
|
+
//
|
|
916
|
+
UAConditionImpl.with_condition_method(inputArguments, context, callback, (conditionEventId, comment, branch, conditionNode) => {
|
|
917
|
+
(0, node_opcua_assert_1.assert)(inputArguments instanceof Array);
|
|
918
|
+
(0, node_opcua_assert_1.assert)(conditionEventId instanceof Buffer || conditionEventId === null);
|
|
919
|
+
(0, node_opcua_assert_1.assert)(branch instanceof condition_snapshot_impl_1.ConditionSnapshotImpl);
|
|
920
|
+
branch.setComment(comment);
|
|
921
|
+
const sourceName = "Method/AddComment";
|
|
922
|
+
conditionNode._raiseAuditConditionCommentEvent(sourceName, conditionEventId, comment);
|
|
923
|
+
// raise new event
|
|
924
|
+
conditionNode.raiseConditionEvent(branch, true);
|
|
925
|
+
/**
|
|
926
|
+
* raised when the branch has been added a comment
|
|
927
|
+
* @event addComment
|
|
928
|
+
* @param conditionEventId NodeId|null
|
|
929
|
+
* @param comment {LocalizedText}
|
|
930
|
+
* @param branch {ConditionSnapshot}
|
|
931
|
+
*/
|
|
932
|
+
conditionNode.emit("addComment", conditionEventId, comment, branch);
|
|
933
|
+
return node_opcua_status_code_1.StatusCodes.Good;
|
|
934
|
+
});
|
|
935
|
+
}
|
|
936
|
+
function sameBuffer(b1, b2) {
|
|
937
|
+
if (!b1 && !b2) {
|
|
938
|
+
return true;
|
|
939
|
+
}
|
|
940
|
+
if (b1 && !b2) {
|
|
941
|
+
return false;
|
|
942
|
+
}
|
|
943
|
+
if (!b1 && b2) {
|
|
944
|
+
return false;
|
|
945
|
+
}
|
|
946
|
+
(0, node_opcua_assert_1.assert)(b1 instanceof Buffer);
|
|
947
|
+
(0, node_opcua_assert_1.assert)(b2 instanceof Buffer);
|
|
948
|
+
if (b1.length !== b2.length) {
|
|
949
|
+
return false;
|
|
950
|
+
}
|
|
951
|
+
/*
|
|
952
|
+
var bb1 = (Buffer.from(b1)).toString("hex");
|
|
953
|
+
var bb2 = (Buffer.from(b2)).toString("hex");
|
|
954
|
+
return bb1 === bb2;
|
|
955
|
+
*/
|
|
956
|
+
const n = b1.length;
|
|
957
|
+
for (let i = 0; i < n; i++) {
|
|
958
|
+
if (b1[i] !== b2[i]) {
|
|
959
|
+
return false;
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
return true;
|
|
963
|
+
}
|
|
964
|
+
function _create_new_branch_id() {
|
|
965
|
+
return (0, node_opcua_nodeid_1.makeNodeId)((0, node_opcua_basic_types_1.randomGuid)(), 1);
|
|
966
|
+
}
|
|
967
|
+
function _update_sourceTimestamp(dataValue /*, indexRange*/) {
|
|
968
|
+
this.sourceTimestamp.setValueFromSource({
|
|
969
|
+
dataType: node_opcua_variant_1.DataType.DateTime,
|
|
970
|
+
value: dataValue.sourceTimestamp
|
|
971
|
+
});
|
|
972
|
+
}
|
|
973
|
+
// tslint:disable:no-console
|
|
974
|
+
function _install_condition_variable_type(node) {
|
|
975
|
+
// from spec 1.03 : 5.3 condition variables
|
|
976
|
+
// However, a change in their value is considered important and supposed to trigger
|
|
977
|
+
// an Event Notification. These information elements are called ConditionVariables.
|
|
978
|
+
if (node.sourceTimestamp) {
|
|
979
|
+
node.sourceTimestamp.accessLevel = (0, node_opcua_data_model_1.makeAccessLevelFlag)("CurrentRead");
|
|
980
|
+
}
|
|
981
|
+
else {
|
|
982
|
+
console.warn("cannot find node.sourceTimestamp", node.browseName.toString());
|
|
983
|
+
}
|
|
984
|
+
node.accessLevel = (0, node_opcua_data_model_1.makeAccessLevelFlag)("CurrentRead");
|
|
985
|
+
// from spec 1.03 : 5.3 condition variables
|
|
986
|
+
// a condition VariableType has a sourceTimeStamp exposed property
|
|
987
|
+
// SourceTimestamp indicates the time of the last change of the Value of this ConditionVariable.
|
|
988
|
+
// It shall be the same time that would be returned from the Read Service inside the DataValue
|
|
989
|
+
// structure for the ConditionVariable Value Attribute.
|
|
990
|
+
(0, node_opcua_assert_1.assert)(node.typeDefinitionObj.browseName.toString() === "ConditionVariableType");
|
|
991
|
+
(0, node_opcua_assert_1.assert)(node.sourceTimestamp.browseName.toString() === "SourceTimestamp");
|
|
992
|
+
node.on("value_changed", _update_sourceTimestamp);
|
|
993
|
+
}
|
|
994
|
+
/**
|
|
995
|
+
* @method _getCompositeKey
|
|
996
|
+
* @param node {BaseNode}
|
|
997
|
+
* @param key {String}
|
|
998
|
+
* @return {BaseNode}
|
|
999
|
+
* @private
|
|
1000
|
+
*
|
|
1001
|
+
* @example
|
|
1002
|
+
*
|
|
1003
|
+
* var node = _getComposite(node,"enabledState.id");
|
|
1004
|
+
*
|
|
1005
|
+
*/
|
|
1006
|
+
function _getCompositeKey(node, key) {
|
|
1007
|
+
let cur = node;
|
|
1008
|
+
const elements = key.split(".");
|
|
1009
|
+
for (const e of elements) {
|
|
1010
|
+
// istanbul ignore next
|
|
1011
|
+
if (!Object.prototype.hasOwnProperty.call(cur, e)) {
|
|
1012
|
+
throw new Error(" cannot extract '" + key + "' from " + node.browseName.toString());
|
|
1013
|
+
}
|
|
1014
|
+
cur = cur[e];
|
|
1015
|
+
}
|
|
1016
|
+
return cur;
|
|
1017
|
+
}
|
|
1018
|
+
/**
|
|
1019
|
+
* verify that the subscription id belongs to the session that make the call.
|
|
1020
|
+
* @method _check_subscription_id_is_valid
|
|
1021
|
+
* @param subscriptionId {Number}
|
|
1022
|
+
* @param context {Object}
|
|
1023
|
+
* @private
|
|
1024
|
+
*/
|
|
1025
|
+
function _check_subscription_id_is_valid(subscriptionId, context) {
|
|
1026
|
+
/// todo: return StatusCodes.BadSubscriptionIdInvalid; if subscriptionId doesn't belong to session...
|
|
1027
|
+
return node_opcua_status_code_1.StatusCodes.Good;
|
|
1028
|
+
}
|
|
1029
1029
|
//# sourceMappingURL=ua_condition_impl.js.map
|