node-opcua-address-space 2.76.0 → 2.77.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/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.js.map +1 -1
- 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 +42 -40
- package/src/ua_variable_impl.ts +3 -2
|
@@ -1,631 +1,631 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* @module node-opcua-address-space
|
|
4
|
-
* @class IAddressSpace
|
|
5
|
-
*/
|
|
6
|
-
// tslint:disable:no-console
|
|
7
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
-
exports.AddressSpace_installHistoricalDataNode = exports.VariableHistorian = void 0;
|
|
9
|
-
const chalk = require("chalk");
|
|
10
|
-
const node_opcua_assert_1 = require("node-opcua-assert");
|
|
11
|
-
const node_opcua_data_model_1 = require("node-opcua-data-model");
|
|
12
|
-
const node_opcua_date_time_1 = require("node-opcua-date-time");
|
|
13
|
-
const node_opcua_service_history_1 = require("node-opcua-service-history");
|
|
14
|
-
const node_opcua_status_code_1 = require("node-opcua-status-code");
|
|
15
|
-
const node_opcua_variant_1 = require("node-opcua-variant");
|
|
16
|
-
const ua_variable_impl_1 = require("../ua_variable_impl");
|
|
17
|
-
const address_space_ts_1 = require("../../source/address_space_ts");
|
|
18
|
-
// tslint:disable:no-var-requires
|
|
19
|
-
const Dequeue = require("dequeue");
|
|
20
|
-
/* interface Historian */
|
|
21
|
-
// {
|
|
22
|
-
//
|
|
23
|
-
// }
|
|
24
|
-
function inInTimeRange(historyReadDetails, dataValue) {
|
|
25
|
-
if (historyReadDetails.startTime &&
|
|
26
|
-
!(0, node_opcua_date_time_1.isMinDate)(historyReadDetails.startTime) &&
|
|
27
|
-
dataValue.sourceTimestamp < historyReadDetails.startTime) {
|
|
28
|
-
return false;
|
|
29
|
-
}
|
|
30
|
-
if (historyReadDetails.endTime &&
|
|
31
|
-
!(0, node_opcua_date_time_1.isMinDate)(historyReadDetails.endTime) &&
|
|
32
|
-
dataValue.sourceTimestamp > historyReadDetails.endTime) {
|
|
33
|
-
return false;
|
|
34
|
-
}
|
|
35
|
-
return true;
|
|
36
|
-
}
|
|
37
|
-
function inInTimeRange2(historyReadDetails, dataValue) {
|
|
38
|
-
if (historyReadDetails.endTime &&
|
|
39
|
-
!(0, node_opcua_date_time_1.isMinDate)(historyReadDetails.endTime) &&
|
|
40
|
-
dataValue.sourceTimestamp > historyReadDetails.endTime) {
|
|
41
|
-
return false;
|
|
42
|
-
}
|
|
43
|
-
return !(historyReadDetails.startTime &&
|
|
44
|
-
!(0, node_opcua_date_time_1.isMinDate)(historyReadDetails.startTime) &&
|
|
45
|
-
dataValue.sourceTimestamp < historyReadDetails.startTime);
|
|
46
|
-
}
|
|
47
|
-
function filter_dequeue(q, historyReadRawModifiedDetails, onlyThisNumber, isReversed) {
|
|
48
|
-
const r = [];
|
|
49
|
-
const predicate = isReversed
|
|
50
|
-
? inInTimeRange2.bind(null, historyReadRawModifiedDetails)
|
|
51
|
-
: inInTimeRange.bind(null, historyReadRawModifiedDetails);
|
|
52
|
-
if (isReversed) {
|
|
53
|
-
let c = q.head.prev;
|
|
54
|
-
while (c.data) {
|
|
55
|
-
if (predicate(c.data)) {
|
|
56
|
-
r.push(c.data);
|
|
57
|
-
}
|
|
58
|
-
c = c.prev;
|
|
59
|
-
if (onlyThisNumber && r.length === onlyThisNumber) {
|
|
60
|
-
return r;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
else {
|
|
65
|
-
let c = q.head.next;
|
|
66
|
-
while (c.data) {
|
|
67
|
-
if (predicate(c.data)) {
|
|
68
|
-
r.push(c.data);
|
|
69
|
-
}
|
|
70
|
-
c = c.next;
|
|
71
|
-
if (onlyThisNumber && r.length === onlyThisNumber) {
|
|
72
|
-
return r;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
return r;
|
|
77
|
-
}
|
|
78
|
-
class VariableHistorian {
|
|
79
|
-
constructor(node, options) {
|
|
80
|
-
this._timeline = new Dequeue(); // is is ordered here ??????
|
|
81
|
-
this._maxOnlineValues = options.maxOnlineValues || 1000;
|
|
82
|
-
this.lastDate = new Date(1600, 0, 1, 0, 0, 0);
|
|
83
|
-
this.lastDatePicoSeconds = 0;
|
|
84
|
-
this.node = node;
|
|
85
|
-
}
|
|
86
|
-
/* public */
|
|
87
|
-
push(newDataValue) {
|
|
88
|
-
this._timeline.push(newDataValue);
|
|
89
|
-
const sourceTime = newDataValue.sourceTimestamp || new Date();
|
|
90
|
-
const sourcePicoSeconds = newDataValue.sourcePicoseconds || 0;
|
|
91
|
-
// ensure that values are set with date increasing
|
|
92
|
-
if (sourceTime.getTime() <= this.lastDate.getTime()) {
|
|
93
|
-
if (!(sourceTime.getTime() === this.lastDate.getTime() && sourcePicoSeconds > this.lastDatePicoSeconds)) {
|
|
94
|
-
console.log(chalk.red("Warning date not increasing "), newDataValue.toString(), " last known date = ", this.lastDate);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
this.lastDate = sourceTime;
|
|
98
|
-
this.lastDatePicoSeconds = newDataValue.sourcePicoseconds || 0;
|
|
99
|
-
// we keep only a limited amount in main memory
|
|
100
|
-
if (this._timeline.length > this._maxOnlineValues) {
|
|
101
|
-
(0, node_opcua_assert_1.assert)(typeof this._maxOnlineValues === "number" && this._maxOnlineValues > 0);
|
|
102
|
-
while (this._timeline.length > this._maxOnlineValues) {
|
|
103
|
-
this._timeline.shift();
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
if (this._timeline.length >= this._maxOnlineValues || this._timeline.length === 1) {
|
|
107
|
-
const first = this._timeline.first();
|
|
108
|
-
this.node._update_startOfOnlineArchive(first.sourceTimestamp);
|
|
109
|
-
// we update the node startOnlineDate
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
extractDataValues(historyReadRawModifiedDetails, maxNumberToExtract, isReversed, reverseDataValue, callback) {
|
|
113
|
-
(0, node_opcua_assert_1.assert)(typeof callback === 'function');
|
|
114
|
-
let dataValues = filter_dequeue(this._timeline, historyReadRawModifiedDetails, maxNumberToExtract, isReversed);
|
|
115
|
-
if (reverseDataValue) {
|
|
116
|
-
dataValues = dataValues.reverse();
|
|
117
|
-
}
|
|
118
|
-
callback(null, dataValues);
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
exports.VariableHistorian = VariableHistorian;
|
|
122
|
-
function _get_startOfOfflineArchive(node) {
|
|
123
|
-
var _a;
|
|
124
|
-
if (!node.$historicalDataConfiguration) {
|
|
125
|
-
throw new Error("this variable has no HistoricalDataConfiguration");
|
|
126
|
-
}
|
|
127
|
-
return (_a = node.$historicalDataConfiguration.startOfArchive) === null || _a === void 0 ? void 0 : _a.readValue();
|
|
128
|
-
}
|
|
129
|
-
function _get_startOfArchive(node) {
|
|
130
|
-
var _a;
|
|
131
|
-
if (!node.$historicalDataConfiguration) {
|
|
132
|
-
throw new Error("this variable has no HistoricalDataConfiguration");
|
|
133
|
-
}
|
|
134
|
-
return (_a = node.$historicalDataConfiguration.startOfArchive) === null || _a === void 0 ? void 0 : _a.readValue();
|
|
135
|
-
}
|
|
136
|
-
function _update_startOfArchive(newDate) {
|
|
137
|
-
var _a;
|
|
138
|
-
if (!this.$historicalDataConfiguration) {
|
|
139
|
-
throw new Error("this variable has no HistoricalDataConfiguration");
|
|
140
|
-
}
|
|
141
|
-
(_a = this.$historicalDataConfiguration.startOfArchive) === null || _a === void 0 ? void 0 : _a.setValueFromSource({
|
|
142
|
-
dataType: node_opcua_variant_1.DataType.DateTime,
|
|
143
|
-
value: newDate
|
|
144
|
-
});
|
|
145
|
-
}
|
|
146
|
-
function _update_startOfOnlineArchive(newDate) {
|
|
147
|
-
var _a;
|
|
148
|
-
if (!this.$historicalDataConfiguration) {
|
|
149
|
-
throw new Error("this variable has no HistoricalDataConfiguration");
|
|
150
|
-
}
|
|
151
|
-
// The StartOfArchive Variable specifies the date before which there is no data
|
|
152
|
-
// in the archive either online or offline.
|
|
153
|
-
// The StartOfOnlineArchive Variable specifies the date of the earliest data
|
|
154
|
-
// in the online archive.
|
|
155
|
-
(_a = this.$historicalDataConfiguration.startOfOnlineArchive) === null || _a === void 0 ? void 0 : _a.setValueFromSource({
|
|
156
|
-
dataType: node_opcua_variant_1.DataType.DateTime,
|
|
157
|
-
value: newDate
|
|
158
|
-
});
|
|
159
|
-
const startOfArchiveDataValue = _get_startOfOfflineArchive(this);
|
|
160
|
-
if (startOfArchiveDataValue &&
|
|
161
|
-
(startOfArchiveDataValue.statusCode !== node_opcua_status_code_1.StatusCodes.Good ||
|
|
162
|
-
!startOfArchiveDataValue.value ||
|
|
163
|
-
!startOfArchiveDataValue.value.value ||
|
|
164
|
-
startOfArchiveDataValue.value.value.getTime() >= newDate.getTime())) {
|
|
165
|
-
this._update_startOfArchive(newDate);
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
ua_variable_impl_1.UAVariableImpl.prototype._update_startOfOnlineArchive = _update_startOfOnlineArchive;
|
|
169
|
-
ua_variable_impl_1.UAVariableImpl.prototype._update_startOfArchive = _update_startOfArchive;
|
|
170
|
-
function _historyPush(newDataValue) {
|
|
171
|
-
if (!this.varHistorian) {
|
|
172
|
-
throw new Error("this variable has no HistoricalDataConfiguration");
|
|
173
|
-
}
|
|
174
|
-
(0, node_opcua_assert_1.assert)(Object.prototype.hasOwnProperty.call(this, "historizing"), "expecting a historizing attribute on node");
|
|
175
|
-
if (!this.historizing) {
|
|
176
|
-
return; //
|
|
177
|
-
}
|
|
178
|
-
(0, node_opcua_assert_1.assert)(this.historizing === true);
|
|
179
|
-
this.varHistorian.push(newDataValue);
|
|
180
|
-
}
|
|
181
|
-
function _historyReadModify(context, historyReadRawModifiedDetails, indexRange, dataEncoding, continuationData, callback) {
|
|
182
|
-
//
|
|
183
|
-
// 6.4.3.3 Read modified functionality
|
|
184
|
-
// Release 1.03 26 OPC Unified Architecture, Part 11
|
|
185
|
-
//
|
|
186
|
-
// When this structure is used for reading Modified Values (isReadModified is set to TRUE), it
|
|
187
|
-
// reads the modified values, StatusCodes, timestamps, modification type, the user identifier,
|
|
188
|
-
// and the timestamp of the modification from the history database for the specified time domain
|
|
189
|
-
// for one or more HistoricalDataNodes. If there are multiple replaced values the Server shall
|
|
190
|
-
// return all of them. The updateType specifies what value is returned in the modification record.
|
|
191
|
-
// If the updateType is INSERT the value is the new value that was inserted. If the updateType
|
|
192
|
-
// is anything else the value is the old value that was changed. See 6.8 HistoryUpdateDetails
|
|
193
|
-
// parameter for details on what updateTypes are available.
|
|
194
|
-
// The purpose of this function is to read values from history that have been Modified. The
|
|
195
|
-
// returnBounds parameter shall be set to FALSE for this case, otherwise the Server returns a
|
|
196
|
-
// BadInvalidArgument StatusCode.
|
|
197
|
-
// The domain of the request is defined by startTime, endTime, and numValuesPerNode; at least
|
|
198
|
-
// two of these shall be specified. If endTime is less than startTime, or endTime and
|
|
199
|
-
// numValuesPerNode alone are specified, then the data shall be returned in reverse order with
|
|
200
|
-
// the later data coming first. If all three are specified then the call shall return up to
|
|
201
|
-
// numValuesPerNode results going from StartTime to EndTime, in either ascending or
|
|
202
|
-
// descending order depending on the relative values of StartTime and EndTime. If more than
|
|
203
|
-
// numValuesPerNode values exist within that time range for a given Node then only
|
|
204
|
-
// numValuesPerNode values per Node are returned along with a continuationPoint. When a
|
|
205
|
-
// continuationPoint is returned, a Client wanting the next numValuesPerNode values should call
|
|
206
|
-
// ReadRaw again with the continuationPoint set. If numValuesPerNode is 0 then all of the
|
|
207
|
-
// values in the range are returned. If the Server cannot return all modified values for a given
|
|
208
|
-
// timestamp in a single response then it shall return modified values with the same timestamp
|
|
209
|
-
// in subsequent calls.
|
|
210
|
-
// If the request takes a long time to process then the Server can return partial results with a
|
|
211
|
-
// ContinuationPoint. This might be done if the request is going to take more time than the Client
|
|
212
|
-
// timeout hint. It may take longer than the Client timeout hint to retrieve any results. In this case
|
|
213
|
-
// the Server may return zero results with a ContinuationPoint that allows the Server to resume
|
|
214
|
-
// the calculation on the next Client HistoryRead call.
|
|
215
|
-
// If a value has been modified multiple times then all values for the time are returned. This
|
|
216
|
-
// means that a timestamp can appear in the array more than once. The order of the returned
|
|
217
|
-
// values with the same timestamp should be from the most recent to oldest modification
|
|
218
|
-
// timestamp, if startTime is less than or equal to endTime. If endTime is less than startTime,
|
|
219
|
-
// then the order of the returned values will be from the oldest modification timestamp to the
|
|
220
|
-
// most recent. It is Server dependent whether multiple modifications are kept or only the most
|
|
221
|
-
// recent.
|
|
222
|
-
// A Server does not have to create a modification record for data when it is first added to the
|
|
223
|
-
// historical collection. If it does then it shall set the ExtraData bit and the Client can read the
|
|
224
|
-
// modification record using a ReadModified call. If the data is subsequently modified the Server
|
|
225
|
-
// shall create a second modification record which is returned along with the original
|
|
226
|
-
// modification record whenever a Client uses the ReadModified call if the Server supports
|
|
227
|
-
// multiple modification records per timestamp.
|
|
228
|
-
// If the requested TimestampsToReturn is not supported for a Node then the operation shall
|
|
229
|
-
// return the BadTimestampNotSupported StatusCode.
|
|
230
|
-
// todo : provide correct implementation
|
|
231
|
-
const result = new node_opcua_service_history_1.HistoryReadResult({
|
|
232
|
-
historyData: new node_opcua_service_history_1.HistoryData({ dataValues: [] }),
|
|
233
|
-
statusCode: node_opcua_status_code_1.StatusCodes.BadUnexpectedError
|
|
234
|
-
});
|
|
235
|
-
return callback(null, result);
|
|
236
|
-
}
|
|
237
|
-
function _historyReadRawAsync(historyReadRawModifiedDetails, maxNumberToExtract, isReversed, reverseDataValue, callback) {
|
|
238
|
-
(0, node_opcua_assert_1.assert)(typeof callback === 'function');
|
|
239
|
-
this.varHistorian.extractDataValues(historyReadRawModifiedDetails, maxNumberToExtract, isReversed, reverseDataValue, callback);
|
|
240
|
-
}
|
|
241
|
-
function _historyReadRaw(context, historyReadRawModifiedDetails, indexRange, dataEncoding, continuationData, callback) {
|
|
242
|
-
(0, node_opcua_assert_1.assert)(historyReadRawModifiedDetails instanceof node_opcua_service_history_1.ReadRawModifiedDetails);
|
|
243
|
-
// 6.4.3.2 Read raw functionality
|
|
244
|
-
//
|
|
245
|
-
// When this structure is used for reading Raw Values (isReadModified is set to FALSE), it reads
|
|
246
|
-
// the values, qualities, and timestamps from the history database for the specified time domain
|
|
247
|
-
// for one or more HistoricalDataNodes.
|
|
248
|
-
//
|
|
249
|
-
// This parameter is intended for use by a Client that wants the actual data saved within the historian.
|
|
250
|
-
//
|
|
251
|
-
// The actual data may be compressed or may be all raw data collected for the item depending on the
|
|
252
|
-
// historian and the storage rules invoked when the item values were saved.
|
|
253
|
-
//
|
|
254
|
-
// When returnBounds is TRUE, the Bounding Values for the time domain are returned. The optional Bounding
|
|
255
|
-
// Values are provided to allow the Client to interpolate values for the start and end times when trending
|
|
256
|
-
// the actual data on a display.
|
|
257
|
-
//
|
|
258
|
-
// The time domain of the request is defined by startTime, endTime, and numValuesPerNode;
|
|
259
|
-
// at least two of these shall be specified.
|
|
260
|
-
//
|
|
261
|
-
// If endTime is less than startTime, or endTime and numValuesPerNode alone are specified
|
|
262
|
-
// then the data will be returned in reverse order, with later data coming first as if time
|
|
263
|
-
// were flowing backward.
|
|
264
|
-
//
|
|
265
|
-
// If all three are specified then the call shall return up to numValuesPerNode results going from
|
|
266
|
-
// startTime to endTime, in either ascending or descending order depending on the relative values
|
|
267
|
-
// of startTime and endTime.
|
|
268
|
-
//
|
|
269
|
-
// If numValuesPerNode is 0, then all the values in the range are returned.
|
|
270
|
-
//
|
|
271
|
-
// A default value of DateTime.MinValue (see Part 6) is used to indicate when startTime or
|
|
272
|
-
// endTime is not specified.
|
|
273
|
-
//
|
|
274
|
-
// It is specifically allowed for the startTime and the endTime to be identical.
|
|
275
|
-
// This allows the Client to request just one value.
|
|
276
|
-
// When the startTime and endTime are identical then time is presumed to be flowing forward.
|
|
277
|
-
// It is specifically not allowed for the Server to return a Bad_InvalidArgument StatusCode
|
|
278
|
-
// if the requested time domain is outside of the Server's range. Such a case shall be treated
|
|
279
|
-
// as an interval in which no data exists.
|
|
280
|
-
//
|
|
281
|
-
// If a startTime, endTime and numValuesPerNode are all provided and if more than
|
|
282
|
-
// numValuesPerNode values exist within that time range for a given Node then only
|
|
283
|
-
// numValuesPerNode values per Node are returned along with a continuationPoint.
|
|
284
|
-
//
|
|
285
|
-
// When a continuationPoint is returned, a Client wanting the next numValuesPerNode values
|
|
286
|
-
// should call ReadRaw again with the continuationPoint set.
|
|
287
|
-
//
|
|
288
|
-
// If the request takes a long time to process then the Server can return partial results with a
|
|
289
|
-
// ContinuationPoint. This might be done if the request is going to take more time than the Client
|
|
290
|
-
// timeout hint. It may take longer than the Client timeout hint to retrieve any results.
|
|
291
|
-
// In this case the Server may return zero results with a ContinuationPoint that allows the
|
|
292
|
-
// Server to resume the calculation on the next Client HistoryRead call.
|
|
293
|
-
//
|
|
294
|
-
// If Bounding Values are requested and a non-zero numValuesPerNode was specified then any
|
|
295
|
-
// Bounding Values returned are included in the numValuesPerNode count.
|
|
296
|
-
//
|
|
297
|
-
// If numValuesPerNode is 1 then only the start bound is returned (the end bound if the reverse
|
|
298
|
-
// order is needed).
|
|
299
|
-
//
|
|
300
|
-
// If numValuesPerNode is 2 then the start bound and the first data point are
|
|
301
|
-
// returned (the end bound if reverse order is needed).
|
|
302
|
-
//
|
|
303
|
-
// When Bounding Values are requested and no bounding value is found then the corresponding
|
|
304
|
-
// StatusCode entry will be set to Bad_BoundNotFound, a timestamp equal to the start or end time
|
|
305
|
-
// as appropriate, and a value of null.
|
|
306
|
-
// How far back or forward to look in history for Bounding Values is Server dependent.
|
|
307
|
-
//
|
|
308
|
-
// For an interval in which no data exists, if Bounding Values are not requested, then the
|
|
309
|
-
// corresponding StatusCode shall be Good_NoData. If Bounding Values are requested and one
|
|
310
|
-
// or both exist, then the result code returned is Success and the bounding value(s) are
|
|
311
|
-
// returned.
|
|
312
|
-
//
|
|
313
|
-
// For cases where there are multiple values for a given timestamp, all but the most recent are
|
|
314
|
-
// considered to be Modified values and the Server shall return the most recent value. If the
|
|
315
|
-
// Server returns a value which hides other values at a timestamp then it shall set the ExtraData
|
|
316
|
-
// bit in the StatusCode associated with that value. If the Server contains additional information
|
|
317
|
-
// regarding a value then the ExtraData bit shall also be set. It indicates that ModifiedValues are
|
|
318
|
-
// available for retrieval, see 6.4.3.3.
|
|
319
|
-
//
|
|
320
|
-
// If the requested TimestampsToReturn is not supported for a Node, the operation shall return
|
|
321
|
-
// the Bad_TimestampNotSupported StatusCode.
|
|
322
|
-
const session = context.session;
|
|
323
|
-
if (!session) {
|
|
324
|
-
throw new Error("Internal Error: context.session not defined");
|
|
325
|
-
}
|
|
326
|
-
if (continuationData.continuationPoint) {
|
|
327
|
-
const cnt = session.continuationPointManager.getNextHistoryReadRaw(historyReadRawModifiedDetails.numValuesPerNode, continuationData);
|
|
328
|
-
const { statusCode, values } = cnt;
|
|
329
|
-
const result2 = new node_opcua_service_history_1.HistoryReadResult({
|
|
330
|
-
continuationPoint: cnt.continuationPoint,
|
|
331
|
-
historyData: new node_opcua_service_history_1.HistoryData({ dataValues: values }),
|
|
332
|
-
statusCode
|
|
333
|
-
});
|
|
334
|
-
return callback(null, result2);
|
|
335
|
-
}
|
|
336
|
-
// todo add special treatment for when startTime > endTime
|
|
337
|
-
// ( in this case series must be return in reverse order )
|
|
338
|
-
let maxNumberToExtract = 0;
|
|
339
|
-
let isReversed = false;
|
|
340
|
-
let reverseDataValue = false;
|
|
341
|
-
if ((0, node_opcua_date_time_1.isMinDate)(historyReadRawModifiedDetails.endTime)) {
|
|
342
|
-
// end time is not specified
|
|
343
|
-
maxNumberToExtract = historyReadRawModifiedDetails.numValuesPerNode;
|
|
344
|
-
if ((0, node_opcua_date_time_1.isMinDate)(historyReadRawModifiedDetails.startTime)) {
|
|
345
|
-
// end start and start time are not specified, this is invalid
|
|
346
|
-
const result = new node_opcua_service_history_1.HistoryReadResult({
|
|
347
|
-
statusCode: node_opcua_status_code_1.StatusCodes.BadHistoryOperationUnsupported // should be an error
|
|
348
|
-
});
|
|
349
|
-
return callback(null, result);
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
else if ((0, node_opcua_date_time_1.isMinDate)(historyReadRawModifiedDetails.startTime)) {
|
|
353
|
-
// start time is not specified
|
|
354
|
-
// end time is specified
|
|
355
|
-
maxNumberToExtract = historyReadRawModifiedDetails.numValuesPerNode;
|
|
356
|
-
isReversed = true;
|
|
357
|
-
reverseDataValue = false;
|
|
358
|
-
if (historyReadRawModifiedDetails.numValuesPerNode === 0) {
|
|
359
|
-
// when start time is not specified
|
|
360
|
-
// and end time is specified
|
|
361
|
-
// numValuesPerNode shall be greater than 0
|
|
362
|
-
const result = new node_opcua_service_history_1.HistoryReadResult({
|
|
363
|
-
statusCode: node_opcua_status_code_1.StatusCodes.BadHistoryOperationUnsupported // should be an error
|
|
364
|
-
});
|
|
365
|
-
return callback(null, result);
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
else {
|
|
369
|
-
// start time is specified
|
|
370
|
-
// end time is specified
|
|
371
|
-
if (historyReadRawModifiedDetails.endTime.getTime() < historyReadRawModifiedDetails.startTime.getTime()) {
|
|
372
|
-
reverseDataValue = true;
|
|
373
|
-
const tmp = historyReadRawModifiedDetails.endTime;
|
|
374
|
-
historyReadRawModifiedDetails.endTime = historyReadRawModifiedDetails.startTime;
|
|
375
|
-
historyReadRawModifiedDetails.startTime = tmp;
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
/*
|
|
379
|
-
const maxHistoryContinuationPoints = this.engine.serverCapabilities.maxHistoryContinuationPoints;
|
|
380
|
-
if (session.continuationPointManager.hasReachedMaximum(maxHistoryContinuationPoints)) {
|
|
381
|
-
return new HistoryReadResult({ statusCode: StatusCodes.BadNoContinuationPoints });
|
|
382
|
-
}
|
|
383
|
-
*/
|
|
384
|
-
this._historyReadRawAsync(historyReadRawModifiedDetails, maxNumberToExtract, isReversed, reverseDataValue, (err, dataValues) => {
|
|
385
|
-
if (err || !dataValues) {
|
|
386
|
-
return callback(err);
|
|
387
|
-
}
|
|
388
|
-
const cnt = session.continuationPointManager.registerHistoryReadRaw(historyReadRawModifiedDetails.numValuesPerNode, dataValues, continuationData);
|
|
389
|
-
const result = new node_opcua_service_history_1.HistoryReadResult({
|
|
390
|
-
continuationPoint: cnt.continuationPoint,
|
|
391
|
-
historyData: new node_opcua_service_history_1.HistoryData({ dataValues: cnt.values }),
|
|
392
|
-
statusCode: cnt.statusCode
|
|
393
|
-
});
|
|
394
|
-
callback(null, result);
|
|
395
|
-
});
|
|
396
|
-
}
|
|
397
|
-
function _historyReadRawModify(context, historyReadRawModifiedDetails, indexRange, dataEncoding, continuationData, callback) {
|
|
398
|
-
const node = this;
|
|
399
|
-
(0, node_opcua_assert_1.assert)(historyReadRawModifiedDetails instanceof node_opcua_service_history_1.ReadRawModifiedDetails);
|
|
400
|
-
if (!historyReadRawModifiedDetails.isReadModified) {
|
|
401
|
-
return node._historyReadRaw(context, historyReadRawModifiedDetails, indexRange, dataEncoding, continuationData, callback);
|
|
402
|
-
}
|
|
403
|
-
else {
|
|
404
|
-
return node._historyReadModify(context, historyReadRawModifiedDetails, indexRange, dataEncoding, continuationData, callback);
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
function _historyRead(context, historyReadDetails, indexRange, dataEncoding, continuationData, callback) {
|
|
408
|
-
(0, node_opcua_assert_1.assert)(typeof callback === 'function');
|
|
409
|
-
if (historyReadDetails instanceof node_opcua_service_history_1.ReadRawModifiedDetails) {
|
|
410
|
-
// note: only ReadRawModifiedDetails supported at this time
|
|
411
|
-
return this._historyReadRawModify(context, historyReadDetails, indexRange, dataEncoding, continuationData, callback);
|
|
412
|
-
}
|
|
413
|
-
else if (historyReadDetails instanceof node_opcua_service_history_1.ReadEventDetails) {
|
|
414
|
-
// The ReadEventDetails structure is used to read the Events from the history database for the
|
|
415
|
-
// specified time domain for one or more HistoricalEventNodes. The Events are filtered based on
|
|
416
|
-
// the filter structure provided. This filter includes the EventFields that are to be returned. For a
|
|
417
|
-
// complete description of filter refer to Part 4.
|
|
418
|
-
// The startTime and endTime are used to filter on the Time field for Events.
|
|
419
|
-
// The time domain of the request is defined by startTime, endTime, and numValuesPerNode; at
|
|
420
|
-
// least two of these shall be specified. If endTime is less than startTime, or endTime and
|
|
421
|
-
// numValuesPerNode alone are specified then the data will be returned in reverse order with
|
|
422
|
-
// later/newer data provided first as if time were flowing backward. If all three are specified then
|
|
423
|
-
// the call shall return up to numValuesPerNode results going from startTime to endTime, in
|
|
424
|
-
// either ascending or descending order depending on the relative values of startTime and
|
|
425
|
-
// endTime. If numValuesPerNode is 0 then all of the values in the range are returned. The
|
|
426
|
-
// default value is used to indicate when startTime, endTime or numValuesPerNode are not
|
|
427
|
-
// specified.
|
|
428
|
-
// It is specifically allowed for the startTime and the endTime to be identical. This allows the
|
|
429
|
-
// Client to request the Event at a single instance in time. When the startTime and endTime are
|
|
430
|
-
// identical then time is presumed to be flowing forward. If no data exists at the time specified
|
|
431
|
-
// then the Server shall return the Good_NoData StatusCode.
|
|
432
|
-
// If a startTime, endTime and numValuesPerNode are all provided, and if more than
|
|
433
|
-
// numValuesPerNode Events exist within that time range for a given Node, then only
|
|
434
|
-
// numValuesPerNode Events per Node are returned along with a ContinuationPoint. When a
|
|
435
|
-
// ContinuationPoint is returned, a Client wanting the next numValuesPerNode values should
|
|
436
|
-
// call HistoryRead again with the continuationPoint set.
|
|
437
|
-
// If the request takes a long time to process then the Server can return partial results with a
|
|
438
|
-
// ContinuationPoint. This might be done if the request is going to take more time than the Client
|
|
439
|
-
// timeout hint. It may take longer than the Client timeout hint to retrieve any results. In this case
|
|
440
|
-
// the Server may return zero results with a ContinuationPoint that allows the Server to resume
|
|
441
|
-
// the calculation on the next Client HistoryRead call.
|
|
442
|
-
// For an interval in which no data exists, the corresponding StatusCode shall be Good_NoData.
|
|
443
|
-
// The filter parameter is used to determine which historical Events and their corresponding
|
|
444
|
-
// fields are returned. It is possible that the fields of an EventType are available for real time
|
|
445
|
-
// updating, but not available from the historian. In this case a StatusCode value will be returned
|
|
446
|
-
// for any Event field that cannot be returned. The value of the StatusCode shall be
|
|
447
|
-
// Bad_NoData.
|
|
448
|
-
// If the requested TimestampsToReturn is not supported for a Node then the operation shall
|
|
449
|
-
// return the Bad_TimestampNotSupported StatusCode. When reading Events this only applies
|
|
450
|
-
// to Event fields that are of type DataValue.
|
|
451
|
-
// todo provide correct implementation
|
|
452
|
-
const result = new node_opcua_service_history_1.HistoryReadResult({
|
|
453
|
-
historyData: new node_opcua_service_history_1.HistoryData({ dataValues: [] }),
|
|
454
|
-
statusCode: node_opcua_status_code_1.StatusCodes.BadHistoryOperationUnsupported
|
|
455
|
-
});
|
|
456
|
-
return callback(null, result);
|
|
457
|
-
}
|
|
458
|
-
else if (historyReadDetails instanceof node_opcua_service_history_1.ReadProcessedDetails) {
|
|
459
|
-
const addressSpace = this.addressSpace;
|
|
460
|
-
if (!addressSpace._readProcessedDetails) {
|
|
461
|
-
const result = new node_opcua_service_history_1.HistoryReadResult({
|
|
462
|
-
historyData: new node_opcua_service_history_1.HistoryData({}),
|
|
463
|
-
statusCode: node_opcua_status_code_1.StatusCodes.BadHistoryOperationUnsupported
|
|
464
|
-
});
|
|
465
|
-
return callback(null, result);
|
|
466
|
-
}
|
|
467
|
-
else {
|
|
468
|
-
return addressSpace._readProcessedDetails(this, context, historyReadDetails, indexRange, dataEncoding, continuationData, callback);
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
|
-
else if (historyReadDetails instanceof node_opcua_service_history_1.ReadAtTimeDetails) {
|
|
472
|
-
// Release 1.03 28 OPC Unified Architecture, Part 11
|
|
473
|
-
// The ReadAtTimeDetails structure reads the values and qualities from the history database for
|
|
474
|
-
// the specified timestamps for one or more HistoricalDataNodes. This function is intended to
|
|
475
|
-
// provide values to correlate with other values with a known timestamp. For example, a Client
|
|
476
|
-
// may need to read the values of sensors when lab samples were collected.
|
|
477
|
-
// The order of the values and qualities returned shall match the order of the timestamps
|
|
478
|
-
// supplied in the request.
|
|
479
|
-
// When no value exists for a specified timestamp, a value shall be Interpolated from the
|
|
480
|
-
// surrounding values to represent the value at the specified timestamp. The interpolation will
|
|
481
|
-
// follow the same rules as the standard Interpolated Aggregate as outlined in Part 13.
|
|
482
|
-
// If the useSimpleBounds flag is True and Interpolation is required then simple bounding values
|
|
483
|
-
// will be used to calculate the data value. If useSimpleBounds is False and Interpolation is
|
|
484
|
-
// required then interpolated bounding values will be used to calculate the data value. See
|
|
485
|
-
// Part 13 for the definition of simple bounding values and interpolated bounding values.
|
|
486
|
-
// If a value is found for the specified timestamp, then the Server will set the StatusCode
|
|
487
|
-
// InfoBits to be Raw. If the value is Interpolated from the surrounding values, then the Server
|
|
488
|
-
// will set the StatusCode InfoBits to be Interpolated.
|
|
489
|
-
// If the read request is taking a long time to calculate then the Server may return zero results
|
|
490
|
-
// with a ContinuationPoint that allows the Server to resume the calculation on the next Client
|
|
491
|
-
// HistoryRead call.
|
|
492
|
-
// If the requested TimestampsToReturn is not supported for a Node, then the operation shall
|
|
493
|
-
// return the Bad_TimestampNotSupported StatusCode.
|
|
494
|
-
// todo provide correct implementation
|
|
495
|
-
const result = new node_opcua_service_history_1.HistoryReadResult({
|
|
496
|
-
historyData: new node_opcua_service_history_1.HistoryData({ dataValues: [] }),
|
|
497
|
-
statusCode: node_opcua_status_code_1.StatusCodes.BadHistoryOperationUnsupported
|
|
498
|
-
});
|
|
499
|
-
return callback(null, result);
|
|
500
|
-
}
|
|
501
|
-
else {
|
|
502
|
-
const result = new node_opcua_service_history_1.HistoryReadResult({
|
|
503
|
-
historyData: new node_opcua_service_history_1.HistoryData({ dataValues: [] }),
|
|
504
|
-
statusCode: node_opcua_status_code_1.StatusCodes.BadHistoryOperationUnsupported
|
|
505
|
-
});
|
|
506
|
-
return callback(null, result);
|
|
507
|
-
}
|
|
508
|
-
}
|
|
509
|
-
function on_value_change(newDataValue) {
|
|
510
|
-
this._historyPush.call(this, newDataValue);
|
|
511
|
-
}
|
|
512
|
-
/**
|
|
513
|
-
* @method installHistoricalDataNode
|
|
514
|
-
* @param node UAVariable
|
|
515
|
-
* @param [options] {Object}
|
|
516
|
-
* @param [options.maxOnlineValues = 1000]
|
|
517
|
-
*/
|
|
518
|
-
function AddressSpace_installHistoricalDataNode(node, options) {
|
|
519
|
-
var _a, _b, _c;
|
|
520
|
-
address_space_ts_1.AddressSpace.historizerFactory = address_space_ts_1.AddressSpace.historizerFactory || {
|
|
521
|
-
create(node1, options1) {
|
|
522
|
-
return new VariableHistorian(node1, options1);
|
|
523
|
-
}
|
|
524
|
-
};
|
|
525
|
-
(0, node_opcua_assert_1.assert)(node.nodeClass === node_opcua_data_model_1.NodeClass.Variable);
|
|
526
|
-
options = options || {};
|
|
527
|
-
const addressSpace = node.addressSpace;
|
|
528
|
-
// install specific history behavior
|
|
529
|
-
node._historyRead = _historyRead;
|
|
530
|
-
node._historyPush = _historyPush;
|
|
531
|
-
node._historyReadRawModify = _historyReadRawModify;
|
|
532
|
-
node._historyReadModify = _historyReadModify;
|
|
533
|
-
node._historyReadRaw = _historyReadRaw;
|
|
534
|
-
node._historyReadRawAsync = _historyReadRawAsync;
|
|
535
|
-
node.varHistorian = options.historian || address_space_ts_1.AddressSpace.historizerFactory.create(node, options);
|
|
536
|
-
const historicalDataConfigurationType = addressSpace.findObjectType("HistoricalDataConfigurationType");
|
|
537
|
-
if (!historicalDataConfigurationType) {
|
|
538
|
-
throw new Error("cannot find HistoricalDataConfigurationType");
|
|
539
|
-
}
|
|
540
|
-
node.historizing = true;
|
|
541
|
-
// tslint:disable:no-bitwise
|
|
542
|
-
node.accessLevel = node.accessLevel | node_opcua_data_model_1.AccessLevelFlag.CurrentRead | node_opcua_data_model_1.AccessLevelFlag.HistoryRead;
|
|
543
|
-
if (node.userAccessLevel !== undefined) {
|
|
544
|
-
node.userAccessLevel = node.userAccessLevel | node_opcua_data_model_1.AccessLevelFlag.CurrentRead | node_opcua_data_model_1.AccessLevelFlag.HistoryRead;
|
|
545
|
-
}
|
|
546
|
-
const optionals = ["Stepped", "Definition", "MaxTimeInterval", "MinTimeInterval", "StartOfArchive", "StartOfOnlineArchive"];
|
|
547
|
-
// Note from spec : If a HistoricalDataNode has configuration defined then one
|
|
548
|
-
// instance shall have a BrowseName of ‘HA Configuration’
|
|
549
|
-
const historicalDataConfiguration = historicalDataConfigurationType.instantiate({
|
|
550
|
-
browseName: { name: "HA Configuration", namespaceIndex: 0 },
|
|
551
|
-
optionals
|
|
552
|
-
});
|
|
553
|
-
// All Historical Configuration Objects shall be referenced using the HasHistoricalConfiguration ReferenceType.
|
|
554
|
-
node.addReference({
|
|
555
|
-
isForward: true,
|
|
556
|
-
nodeId: historicalDataConfiguration.nodeId,
|
|
557
|
-
referenceType: "HasHistoricalConfiguration"
|
|
558
|
-
});
|
|
559
|
-
// The Stepped Variable specifies whether the historical data was collected in such a manner
|
|
560
|
-
// that it should be displayed as SlopedInterpolation (sloped line between points) or as
|
|
561
|
-
// SteppedInterpolation (vertically-connected horizontal lines between points) when raw data is
|
|
562
|
-
// examined. This Property also effects how some Aggregates are calculated. A value of True
|
|
563
|
-
// indicates the stepped interpolation mode. A value of False indicates SlopedInterpolation
|
|
564
|
-
// mode. The default value is False.
|
|
565
|
-
historicalDataConfiguration.stepped.setValueFromSource({ dataType: "Boolean", value: false });
|
|
566
|
-
// The MaxTimeInterval Variable specifies the maximum interval between data points in the
|
|
567
|
-
// history repository regardless of their value change (see Part 3 for definition of Duration).
|
|
568
|
-
(_a = historicalDataConfiguration.maxTimeInterval) === null || _a === void 0 ? void 0 : _a.setValueFromSource({ dataType: "Duration", value: 10 * 1000 });
|
|
569
|
-
// The MinTimeInterval Variable specifies the minimum interval between data points in the
|
|
570
|
-
// history repository regardless of their value change
|
|
571
|
-
(_b = historicalDataConfiguration.minTimeInterval) === null || _b === void 0 ? void 0 : _b.setValueFromSource({ dataType: "Duration", value: 0.1 * 1000 });
|
|
572
|
-
// The StartOfArchive Variable specifies the date before which there is no data in the archive
|
|
573
|
-
// either online or offline.
|
|
574
|
-
// The StartOfOnlineArchive Variable specifies the date of the earliest data in the online archive.
|
|
575
|
-
const startOfOnlineArchive = new Date();
|
|
576
|
-
(_c = historicalDataConfiguration.startOfOnlineArchive) === null || _c === void 0 ? void 0 : _c.setValueFromSource({
|
|
577
|
-
dataType: node_opcua_variant_1.DataType.DateTime,
|
|
578
|
-
value: startOfOnlineArchive
|
|
579
|
-
});
|
|
580
|
-
// TreatUncertainAsBad
|
|
581
|
-
// The TreatUncertainAsBad Variable indicates how the Server treats data returned with a
|
|
582
|
-
// StatusCode severity Uncertain with respect to Aggregate calculations. A value of True indicates
|
|
583
|
-
// the Server considers the severity equivalent to Bad, a value of False indicates the Server
|
|
584
|
-
// considers the severity equivalent to Good, unless the Aggregate definition says otherwise. The
|
|
585
|
-
// default value is True. Note that the value is still treated as Uncertain when the StatusCode for
|
|
586
|
-
// the result is calculated.
|
|
587
|
-
historicalDataConfiguration.aggregateConfiguration.treatUncertainAsBad.setValueFromSource({
|
|
588
|
-
dataType: "Boolean",
|
|
589
|
-
value: true
|
|
590
|
-
});
|
|
591
|
-
// The PercentDataBad Variable indicates the minimum percentage of Bad data in a given interval required for the
|
|
592
|
-
// StatusCode for the given interval for processed data request to be set to Bad.
|
|
593
|
-
// (Uncertain is treated as defined above.) Refer to 5.4.3 for details on using this Variable when assigning
|
|
594
|
-
// StatusCodes. For details on which Aggregates use the PercentDataBad Variable, see
|
|
595
|
-
// the definition of each Aggregate. The default value is 100.
|
|
596
|
-
historicalDataConfiguration.aggregateConfiguration.percentDataBad.setValueFromSource({
|
|
597
|
-
dataType: "Byte",
|
|
598
|
-
value: 100
|
|
599
|
-
});
|
|
600
|
-
// The PercentDataGood Variable indicates the minimum percentage of Good data in a given
|
|
601
|
-
// interval required for the StatusCode for the given interval for the processed data requests to be
|
|
602
|
-
// set to Good. Refer to 5.4.3 for details on using this Variable when assigning StatusCodes. For
|
|
603
|
-
// details on which Aggregates use the PercentDataGood Variable, see the definition of each
|
|
604
|
-
// Aggregate. The default value is 100.
|
|
605
|
-
historicalDataConfiguration.aggregateConfiguration.percentDataGood.setValueFromSource({
|
|
606
|
-
dataType: "Byte",
|
|
607
|
-
value: 100
|
|
608
|
-
});
|
|
609
|
-
//
|
|
610
|
-
// The PercentDataGood and PercentDataBad shall follow the following relationship
|
|
611
|
-
// PercentDataGood ≥ (100 – PercentDataBad). If they are equal the result of the
|
|
612
|
-
// PercentDataGood calculation is used. If the values entered for PercentDataGood and
|
|
613
|
-
//
|
|
614
|
-
// PercentDataBad do not result in a valid calculation (e.g. Bad = 80; Good = 0) the result will
|
|
615
|
-
// have a StatusCode of Bad_AggregateInvalidInputs The StatusCode
|
|
616
|
-
//
|
|
617
|
-
// Bad_AggregateInvalidInputs will be returned if the value of PercentDataGood or
|
|
618
|
-
// PercentDataBad exceed 100.
|
|
619
|
-
node.$historicalDataConfiguration = historicalDataConfiguration;
|
|
620
|
-
const dataValue = node.readValue();
|
|
621
|
-
if (dataValue.statusCode !== node_opcua_status_code_1.StatusCodes.BadWaitingForInitialData &&
|
|
622
|
-
dataValue.statusCode !== node_opcua_status_code_1.StatusCodes.UncertainInitialValue) {
|
|
623
|
-
on_value_change.call(node, dataValue);
|
|
624
|
-
}
|
|
625
|
-
node.on("value_changed", on_value_change);
|
|
626
|
-
// update the index of historizing nodes in the addressSpace
|
|
627
|
-
node.addressSpace.historizingNodes = node.addressSpace.historizingNodes || {};
|
|
628
|
-
node.addressSpace.historizingNodes[node.nodeId.toString()] = node;
|
|
629
|
-
}
|
|
630
|
-
exports.AddressSpace_installHistoricalDataNode = AddressSpace_installHistoricalDataNode;
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @module node-opcua-address-space
|
|
4
|
+
* @class IAddressSpace
|
|
5
|
+
*/
|
|
6
|
+
// tslint:disable:no-console
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.AddressSpace_installHistoricalDataNode = exports.VariableHistorian = void 0;
|
|
9
|
+
const chalk = require("chalk");
|
|
10
|
+
const node_opcua_assert_1 = require("node-opcua-assert");
|
|
11
|
+
const node_opcua_data_model_1 = require("node-opcua-data-model");
|
|
12
|
+
const node_opcua_date_time_1 = require("node-opcua-date-time");
|
|
13
|
+
const node_opcua_service_history_1 = require("node-opcua-service-history");
|
|
14
|
+
const node_opcua_status_code_1 = require("node-opcua-status-code");
|
|
15
|
+
const node_opcua_variant_1 = require("node-opcua-variant");
|
|
16
|
+
const ua_variable_impl_1 = require("../ua_variable_impl");
|
|
17
|
+
const address_space_ts_1 = require("../../source/address_space_ts");
|
|
18
|
+
// tslint:disable:no-var-requires
|
|
19
|
+
const Dequeue = require("dequeue");
|
|
20
|
+
/* interface Historian */
|
|
21
|
+
// {
|
|
22
|
+
//
|
|
23
|
+
// }
|
|
24
|
+
function inInTimeRange(historyReadDetails, dataValue) {
|
|
25
|
+
if (historyReadDetails.startTime &&
|
|
26
|
+
!(0, node_opcua_date_time_1.isMinDate)(historyReadDetails.startTime) &&
|
|
27
|
+
dataValue.sourceTimestamp < historyReadDetails.startTime) {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
if (historyReadDetails.endTime &&
|
|
31
|
+
!(0, node_opcua_date_time_1.isMinDate)(historyReadDetails.endTime) &&
|
|
32
|
+
dataValue.sourceTimestamp > historyReadDetails.endTime) {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
function inInTimeRange2(historyReadDetails, dataValue) {
|
|
38
|
+
if (historyReadDetails.endTime &&
|
|
39
|
+
!(0, node_opcua_date_time_1.isMinDate)(historyReadDetails.endTime) &&
|
|
40
|
+
dataValue.sourceTimestamp > historyReadDetails.endTime) {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
return !(historyReadDetails.startTime &&
|
|
44
|
+
!(0, node_opcua_date_time_1.isMinDate)(historyReadDetails.startTime) &&
|
|
45
|
+
dataValue.sourceTimestamp < historyReadDetails.startTime);
|
|
46
|
+
}
|
|
47
|
+
function filter_dequeue(q, historyReadRawModifiedDetails, onlyThisNumber, isReversed) {
|
|
48
|
+
const r = [];
|
|
49
|
+
const predicate = isReversed
|
|
50
|
+
? inInTimeRange2.bind(null, historyReadRawModifiedDetails)
|
|
51
|
+
: inInTimeRange.bind(null, historyReadRawModifiedDetails);
|
|
52
|
+
if (isReversed) {
|
|
53
|
+
let c = q.head.prev;
|
|
54
|
+
while (c.data) {
|
|
55
|
+
if (predicate(c.data)) {
|
|
56
|
+
r.push(c.data);
|
|
57
|
+
}
|
|
58
|
+
c = c.prev;
|
|
59
|
+
if (onlyThisNumber && r.length === onlyThisNumber) {
|
|
60
|
+
return r;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
let c = q.head.next;
|
|
66
|
+
while (c.data) {
|
|
67
|
+
if (predicate(c.data)) {
|
|
68
|
+
r.push(c.data);
|
|
69
|
+
}
|
|
70
|
+
c = c.next;
|
|
71
|
+
if (onlyThisNumber && r.length === onlyThisNumber) {
|
|
72
|
+
return r;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return r;
|
|
77
|
+
}
|
|
78
|
+
class VariableHistorian {
|
|
79
|
+
constructor(node, options) {
|
|
80
|
+
this._timeline = new Dequeue(); // is is ordered here ??????
|
|
81
|
+
this._maxOnlineValues = options.maxOnlineValues || 1000;
|
|
82
|
+
this.lastDate = new Date(1600, 0, 1, 0, 0, 0);
|
|
83
|
+
this.lastDatePicoSeconds = 0;
|
|
84
|
+
this.node = node;
|
|
85
|
+
}
|
|
86
|
+
/* public */
|
|
87
|
+
push(newDataValue) {
|
|
88
|
+
this._timeline.push(newDataValue);
|
|
89
|
+
const sourceTime = newDataValue.sourceTimestamp || new Date();
|
|
90
|
+
const sourcePicoSeconds = newDataValue.sourcePicoseconds || 0;
|
|
91
|
+
// ensure that values are set with date increasing
|
|
92
|
+
if (sourceTime.getTime() <= this.lastDate.getTime()) {
|
|
93
|
+
if (!(sourceTime.getTime() === this.lastDate.getTime() && sourcePicoSeconds > this.lastDatePicoSeconds)) {
|
|
94
|
+
console.log(chalk.red("Warning date not increasing "), newDataValue.toString(), " last known date = ", this.lastDate);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
this.lastDate = sourceTime;
|
|
98
|
+
this.lastDatePicoSeconds = newDataValue.sourcePicoseconds || 0;
|
|
99
|
+
// we keep only a limited amount in main memory
|
|
100
|
+
if (this._timeline.length > this._maxOnlineValues) {
|
|
101
|
+
(0, node_opcua_assert_1.assert)(typeof this._maxOnlineValues === "number" && this._maxOnlineValues > 0);
|
|
102
|
+
while (this._timeline.length > this._maxOnlineValues) {
|
|
103
|
+
this._timeline.shift();
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
if (this._timeline.length >= this._maxOnlineValues || this._timeline.length === 1) {
|
|
107
|
+
const first = this._timeline.first();
|
|
108
|
+
this.node._update_startOfOnlineArchive(first.sourceTimestamp);
|
|
109
|
+
// we update the node startOnlineDate
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
extractDataValues(historyReadRawModifiedDetails, maxNumberToExtract, isReversed, reverseDataValue, callback) {
|
|
113
|
+
(0, node_opcua_assert_1.assert)(typeof callback === 'function');
|
|
114
|
+
let dataValues = filter_dequeue(this._timeline, historyReadRawModifiedDetails, maxNumberToExtract, isReversed);
|
|
115
|
+
if (reverseDataValue) {
|
|
116
|
+
dataValues = dataValues.reverse();
|
|
117
|
+
}
|
|
118
|
+
callback(null, dataValues);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
exports.VariableHistorian = VariableHistorian;
|
|
122
|
+
function _get_startOfOfflineArchive(node) {
|
|
123
|
+
var _a;
|
|
124
|
+
if (!node.$historicalDataConfiguration) {
|
|
125
|
+
throw new Error("this variable has no HistoricalDataConfiguration");
|
|
126
|
+
}
|
|
127
|
+
return (_a = node.$historicalDataConfiguration.startOfArchive) === null || _a === void 0 ? void 0 : _a.readValue();
|
|
128
|
+
}
|
|
129
|
+
function _get_startOfArchive(node) {
|
|
130
|
+
var _a;
|
|
131
|
+
if (!node.$historicalDataConfiguration) {
|
|
132
|
+
throw new Error("this variable has no HistoricalDataConfiguration");
|
|
133
|
+
}
|
|
134
|
+
return (_a = node.$historicalDataConfiguration.startOfArchive) === null || _a === void 0 ? void 0 : _a.readValue();
|
|
135
|
+
}
|
|
136
|
+
function _update_startOfArchive(newDate) {
|
|
137
|
+
var _a;
|
|
138
|
+
if (!this.$historicalDataConfiguration) {
|
|
139
|
+
throw new Error("this variable has no HistoricalDataConfiguration");
|
|
140
|
+
}
|
|
141
|
+
(_a = this.$historicalDataConfiguration.startOfArchive) === null || _a === void 0 ? void 0 : _a.setValueFromSource({
|
|
142
|
+
dataType: node_opcua_variant_1.DataType.DateTime,
|
|
143
|
+
value: newDate
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
function _update_startOfOnlineArchive(newDate) {
|
|
147
|
+
var _a;
|
|
148
|
+
if (!this.$historicalDataConfiguration) {
|
|
149
|
+
throw new Error("this variable has no HistoricalDataConfiguration");
|
|
150
|
+
}
|
|
151
|
+
// The StartOfArchive Variable specifies the date before which there is no data
|
|
152
|
+
// in the archive either online or offline.
|
|
153
|
+
// The StartOfOnlineArchive Variable specifies the date of the earliest data
|
|
154
|
+
// in the online archive.
|
|
155
|
+
(_a = this.$historicalDataConfiguration.startOfOnlineArchive) === null || _a === void 0 ? void 0 : _a.setValueFromSource({
|
|
156
|
+
dataType: node_opcua_variant_1.DataType.DateTime,
|
|
157
|
+
value: newDate
|
|
158
|
+
});
|
|
159
|
+
const startOfArchiveDataValue = _get_startOfOfflineArchive(this);
|
|
160
|
+
if (startOfArchiveDataValue &&
|
|
161
|
+
(startOfArchiveDataValue.statusCode !== node_opcua_status_code_1.StatusCodes.Good ||
|
|
162
|
+
!startOfArchiveDataValue.value ||
|
|
163
|
+
!startOfArchiveDataValue.value.value ||
|
|
164
|
+
startOfArchiveDataValue.value.value.getTime() >= newDate.getTime())) {
|
|
165
|
+
this._update_startOfArchive(newDate);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
ua_variable_impl_1.UAVariableImpl.prototype._update_startOfOnlineArchive = _update_startOfOnlineArchive;
|
|
169
|
+
ua_variable_impl_1.UAVariableImpl.prototype._update_startOfArchive = _update_startOfArchive;
|
|
170
|
+
function _historyPush(newDataValue) {
|
|
171
|
+
if (!this.varHistorian) {
|
|
172
|
+
throw new Error("this variable has no HistoricalDataConfiguration");
|
|
173
|
+
}
|
|
174
|
+
(0, node_opcua_assert_1.assert)(Object.prototype.hasOwnProperty.call(this, "historizing"), "expecting a historizing attribute on node");
|
|
175
|
+
if (!this.historizing) {
|
|
176
|
+
return; //
|
|
177
|
+
}
|
|
178
|
+
(0, node_opcua_assert_1.assert)(this.historizing === true);
|
|
179
|
+
this.varHistorian.push(newDataValue);
|
|
180
|
+
}
|
|
181
|
+
function _historyReadModify(context, historyReadRawModifiedDetails, indexRange, dataEncoding, continuationData, callback) {
|
|
182
|
+
//
|
|
183
|
+
// 6.4.3.3 Read modified functionality
|
|
184
|
+
// Release 1.03 26 OPC Unified Architecture, Part 11
|
|
185
|
+
//
|
|
186
|
+
// When this structure is used for reading Modified Values (isReadModified is set to TRUE), it
|
|
187
|
+
// reads the modified values, StatusCodes, timestamps, modification type, the user identifier,
|
|
188
|
+
// and the timestamp of the modification from the history database for the specified time domain
|
|
189
|
+
// for one or more HistoricalDataNodes. If there are multiple replaced values the Server shall
|
|
190
|
+
// return all of them. The updateType specifies what value is returned in the modification record.
|
|
191
|
+
// If the updateType is INSERT the value is the new value that was inserted. If the updateType
|
|
192
|
+
// is anything else the value is the old value that was changed. See 6.8 HistoryUpdateDetails
|
|
193
|
+
// parameter for details on what updateTypes are available.
|
|
194
|
+
// The purpose of this function is to read values from history that have been Modified. The
|
|
195
|
+
// returnBounds parameter shall be set to FALSE for this case, otherwise the Server returns a
|
|
196
|
+
// BadInvalidArgument StatusCode.
|
|
197
|
+
// The domain of the request is defined by startTime, endTime, and numValuesPerNode; at least
|
|
198
|
+
// two of these shall be specified. If endTime is less than startTime, or endTime and
|
|
199
|
+
// numValuesPerNode alone are specified, then the data shall be returned in reverse order with
|
|
200
|
+
// the later data coming first. If all three are specified then the call shall return up to
|
|
201
|
+
// numValuesPerNode results going from StartTime to EndTime, in either ascending or
|
|
202
|
+
// descending order depending on the relative values of StartTime and EndTime. If more than
|
|
203
|
+
// numValuesPerNode values exist within that time range for a given Node then only
|
|
204
|
+
// numValuesPerNode values per Node are returned along with a continuationPoint. When a
|
|
205
|
+
// continuationPoint is returned, a Client wanting the next numValuesPerNode values should call
|
|
206
|
+
// ReadRaw again with the continuationPoint set. If numValuesPerNode is 0 then all of the
|
|
207
|
+
// values in the range are returned. If the Server cannot return all modified values for a given
|
|
208
|
+
// timestamp in a single response then it shall return modified values with the same timestamp
|
|
209
|
+
// in subsequent calls.
|
|
210
|
+
// If the request takes a long time to process then the Server can return partial results with a
|
|
211
|
+
// ContinuationPoint. This might be done if the request is going to take more time than the Client
|
|
212
|
+
// timeout hint. It may take longer than the Client timeout hint to retrieve any results. In this case
|
|
213
|
+
// the Server may return zero results with a ContinuationPoint that allows the Server to resume
|
|
214
|
+
// the calculation on the next Client HistoryRead call.
|
|
215
|
+
// If a value has been modified multiple times then all values for the time are returned. This
|
|
216
|
+
// means that a timestamp can appear in the array more than once. The order of the returned
|
|
217
|
+
// values with the same timestamp should be from the most recent to oldest modification
|
|
218
|
+
// timestamp, if startTime is less than or equal to endTime. If endTime is less than startTime,
|
|
219
|
+
// then the order of the returned values will be from the oldest modification timestamp to the
|
|
220
|
+
// most recent. It is Server dependent whether multiple modifications are kept or only the most
|
|
221
|
+
// recent.
|
|
222
|
+
// A Server does not have to create a modification record for data when it is first added to the
|
|
223
|
+
// historical collection. If it does then it shall set the ExtraData bit and the Client can read the
|
|
224
|
+
// modification record using a ReadModified call. If the data is subsequently modified the Server
|
|
225
|
+
// shall create a second modification record which is returned along with the original
|
|
226
|
+
// modification record whenever a Client uses the ReadModified call if the Server supports
|
|
227
|
+
// multiple modification records per timestamp.
|
|
228
|
+
// If the requested TimestampsToReturn is not supported for a Node then the operation shall
|
|
229
|
+
// return the BadTimestampNotSupported StatusCode.
|
|
230
|
+
// todo : provide correct implementation
|
|
231
|
+
const result = new node_opcua_service_history_1.HistoryReadResult({
|
|
232
|
+
historyData: new node_opcua_service_history_1.HistoryData({ dataValues: [] }),
|
|
233
|
+
statusCode: node_opcua_status_code_1.StatusCodes.BadUnexpectedError
|
|
234
|
+
});
|
|
235
|
+
return callback(null, result);
|
|
236
|
+
}
|
|
237
|
+
function _historyReadRawAsync(historyReadRawModifiedDetails, maxNumberToExtract, isReversed, reverseDataValue, callback) {
|
|
238
|
+
(0, node_opcua_assert_1.assert)(typeof callback === 'function');
|
|
239
|
+
this.varHistorian.extractDataValues(historyReadRawModifiedDetails, maxNumberToExtract, isReversed, reverseDataValue, callback);
|
|
240
|
+
}
|
|
241
|
+
function _historyReadRaw(context, historyReadRawModifiedDetails, indexRange, dataEncoding, continuationData, callback) {
|
|
242
|
+
(0, node_opcua_assert_1.assert)(historyReadRawModifiedDetails instanceof node_opcua_service_history_1.ReadRawModifiedDetails);
|
|
243
|
+
// 6.4.3.2 Read raw functionality
|
|
244
|
+
//
|
|
245
|
+
// When this structure is used for reading Raw Values (isReadModified is set to FALSE), it reads
|
|
246
|
+
// the values, qualities, and timestamps from the history database for the specified time domain
|
|
247
|
+
// for one or more HistoricalDataNodes.
|
|
248
|
+
//
|
|
249
|
+
// This parameter is intended for use by a Client that wants the actual data saved within the historian.
|
|
250
|
+
//
|
|
251
|
+
// The actual data may be compressed or may be all raw data collected for the item depending on the
|
|
252
|
+
// historian and the storage rules invoked when the item values were saved.
|
|
253
|
+
//
|
|
254
|
+
// When returnBounds is TRUE, the Bounding Values for the time domain are returned. The optional Bounding
|
|
255
|
+
// Values are provided to allow the Client to interpolate values for the start and end times when trending
|
|
256
|
+
// the actual data on a display.
|
|
257
|
+
//
|
|
258
|
+
// The time domain of the request is defined by startTime, endTime, and numValuesPerNode;
|
|
259
|
+
// at least two of these shall be specified.
|
|
260
|
+
//
|
|
261
|
+
// If endTime is less than startTime, or endTime and numValuesPerNode alone are specified
|
|
262
|
+
// then the data will be returned in reverse order, with later data coming first as if time
|
|
263
|
+
// were flowing backward.
|
|
264
|
+
//
|
|
265
|
+
// If all three are specified then the call shall return up to numValuesPerNode results going from
|
|
266
|
+
// startTime to endTime, in either ascending or descending order depending on the relative values
|
|
267
|
+
// of startTime and endTime.
|
|
268
|
+
//
|
|
269
|
+
// If numValuesPerNode is 0, then all the values in the range are returned.
|
|
270
|
+
//
|
|
271
|
+
// A default value of DateTime.MinValue (see Part 6) is used to indicate when startTime or
|
|
272
|
+
// endTime is not specified.
|
|
273
|
+
//
|
|
274
|
+
// It is specifically allowed for the startTime and the endTime to be identical.
|
|
275
|
+
// This allows the Client to request just one value.
|
|
276
|
+
// When the startTime and endTime are identical then time is presumed to be flowing forward.
|
|
277
|
+
// It is specifically not allowed for the Server to return a Bad_InvalidArgument StatusCode
|
|
278
|
+
// if the requested time domain is outside of the Server's range. Such a case shall be treated
|
|
279
|
+
// as an interval in which no data exists.
|
|
280
|
+
//
|
|
281
|
+
// If a startTime, endTime and numValuesPerNode are all provided and if more than
|
|
282
|
+
// numValuesPerNode values exist within that time range for a given Node then only
|
|
283
|
+
// numValuesPerNode values per Node are returned along with a continuationPoint.
|
|
284
|
+
//
|
|
285
|
+
// When a continuationPoint is returned, a Client wanting the next numValuesPerNode values
|
|
286
|
+
// should call ReadRaw again with the continuationPoint set.
|
|
287
|
+
//
|
|
288
|
+
// If the request takes a long time to process then the Server can return partial results with a
|
|
289
|
+
// ContinuationPoint. This might be done if the request is going to take more time than the Client
|
|
290
|
+
// timeout hint. It may take longer than the Client timeout hint to retrieve any results.
|
|
291
|
+
// In this case the Server may return zero results with a ContinuationPoint that allows the
|
|
292
|
+
// Server to resume the calculation on the next Client HistoryRead call.
|
|
293
|
+
//
|
|
294
|
+
// If Bounding Values are requested and a non-zero numValuesPerNode was specified then any
|
|
295
|
+
// Bounding Values returned are included in the numValuesPerNode count.
|
|
296
|
+
//
|
|
297
|
+
// If numValuesPerNode is 1 then only the start bound is returned (the end bound if the reverse
|
|
298
|
+
// order is needed).
|
|
299
|
+
//
|
|
300
|
+
// If numValuesPerNode is 2 then the start bound and the first data point are
|
|
301
|
+
// returned (the end bound if reverse order is needed).
|
|
302
|
+
//
|
|
303
|
+
// When Bounding Values are requested and no bounding value is found then the corresponding
|
|
304
|
+
// StatusCode entry will be set to Bad_BoundNotFound, a timestamp equal to the start or end time
|
|
305
|
+
// as appropriate, and a value of null.
|
|
306
|
+
// How far back or forward to look in history for Bounding Values is Server dependent.
|
|
307
|
+
//
|
|
308
|
+
// For an interval in which no data exists, if Bounding Values are not requested, then the
|
|
309
|
+
// corresponding StatusCode shall be Good_NoData. If Bounding Values are requested and one
|
|
310
|
+
// or both exist, then the result code returned is Success and the bounding value(s) are
|
|
311
|
+
// returned.
|
|
312
|
+
//
|
|
313
|
+
// For cases where there are multiple values for a given timestamp, all but the most recent are
|
|
314
|
+
// considered to be Modified values and the Server shall return the most recent value. If the
|
|
315
|
+
// Server returns a value which hides other values at a timestamp then it shall set the ExtraData
|
|
316
|
+
// bit in the StatusCode associated with that value. If the Server contains additional information
|
|
317
|
+
// regarding a value then the ExtraData bit shall also be set. It indicates that ModifiedValues are
|
|
318
|
+
// available for retrieval, see 6.4.3.3.
|
|
319
|
+
//
|
|
320
|
+
// If the requested TimestampsToReturn is not supported for a Node, the operation shall return
|
|
321
|
+
// the Bad_TimestampNotSupported StatusCode.
|
|
322
|
+
const session = context.session;
|
|
323
|
+
if (!session) {
|
|
324
|
+
throw new Error("Internal Error: context.session not defined");
|
|
325
|
+
}
|
|
326
|
+
if (continuationData.continuationPoint) {
|
|
327
|
+
const cnt = session.continuationPointManager.getNextHistoryReadRaw(historyReadRawModifiedDetails.numValuesPerNode, continuationData);
|
|
328
|
+
const { statusCode, values } = cnt;
|
|
329
|
+
const result2 = new node_opcua_service_history_1.HistoryReadResult({
|
|
330
|
+
continuationPoint: cnt.continuationPoint,
|
|
331
|
+
historyData: new node_opcua_service_history_1.HistoryData({ dataValues: values }),
|
|
332
|
+
statusCode
|
|
333
|
+
});
|
|
334
|
+
return callback(null, result2);
|
|
335
|
+
}
|
|
336
|
+
// todo add special treatment for when startTime > endTime
|
|
337
|
+
// ( in this case series must be return in reverse order )
|
|
338
|
+
let maxNumberToExtract = 0;
|
|
339
|
+
let isReversed = false;
|
|
340
|
+
let reverseDataValue = false;
|
|
341
|
+
if ((0, node_opcua_date_time_1.isMinDate)(historyReadRawModifiedDetails.endTime)) {
|
|
342
|
+
// end time is not specified
|
|
343
|
+
maxNumberToExtract = historyReadRawModifiedDetails.numValuesPerNode;
|
|
344
|
+
if ((0, node_opcua_date_time_1.isMinDate)(historyReadRawModifiedDetails.startTime)) {
|
|
345
|
+
// end start and start time are not specified, this is invalid
|
|
346
|
+
const result = new node_opcua_service_history_1.HistoryReadResult({
|
|
347
|
+
statusCode: node_opcua_status_code_1.StatusCodes.BadHistoryOperationUnsupported // should be an error
|
|
348
|
+
});
|
|
349
|
+
return callback(null, result);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
else if ((0, node_opcua_date_time_1.isMinDate)(historyReadRawModifiedDetails.startTime)) {
|
|
353
|
+
// start time is not specified
|
|
354
|
+
// end time is specified
|
|
355
|
+
maxNumberToExtract = historyReadRawModifiedDetails.numValuesPerNode;
|
|
356
|
+
isReversed = true;
|
|
357
|
+
reverseDataValue = false;
|
|
358
|
+
if (historyReadRawModifiedDetails.numValuesPerNode === 0) {
|
|
359
|
+
// when start time is not specified
|
|
360
|
+
// and end time is specified
|
|
361
|
+
// numValuesPerNode shall be greater than 0
|
|
362
|
+
const result = new node_opcua_service_history_1.HistoryReadResult({
|
|
363
|
+
statusCode: node_opcua_status_code_1.StatusCodes.BadHistoryOperationUnsupported // should be an error
|
|
364
|
+
});
|
|
365
|
+
return callback(null, result);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
else {
|
|
369
|
+
// start time is specified
|
|
370
|
+
// end time is specified
|
|
371
|
+
if (historyReadRawModifiedDetails.endTime.getTime() < historyReadRawModifiedDetails.startTime.getTime()) {
|
|
372
|
+
reverseDataValue = true;
|
|
373
|
+
const tmp = historyReadRawModifiedDetails.endTime;
|
|
374
|
+
historyReadRawModifiedDetails.endTime = historyReadRawModifiedDetails.startTime;
|
|
375
|
+
historyReadRawModifiedDetails.startTime = tmp;
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
/*
|
|
379
|
+
const maxHistoryContinuationPoints = this.engine.serverCapabilities.maxHistoryContinuationPoints;
|
|
380
|
+
if (session.continuationPointManager.hasReachedMaximum(maxHistoryContinuationPoints)) {
|
|
381
|
+
return new HistoryReadResult({ statusCode: StatusCodes.BadNoContinuationPoints });
|
|
382
|
+
}
|
|
383
|
+
*/
|
|
384
|
+
this._historyReadRawAsync(historyReadRawModifiedDetails, maxNumberToExtract, isReversed, reverseDataValue, (err, dataValues) => {
|
|
385
|
+
if (err || !dataValues) {
|
|
386
|
+
return callback(err);
|
|
387
|
+
}
|
|
388
|
+
const cnt = session.continuationPointManager.registerHistoryReadRaw(historyReadRawModifiedDetails.numValuesPerNode, dataValues, continuationData);
|
|
389
|
+
const result = new node_opcua_service_history_1.HistoryReadResult({
|
|
390
|
+
continuationPoint: cnt.continuationPoint,
|
|
391
|
+
historyData: new node_opcua_service_history_1.HistoryData({ dataValues: cnt.values }),
|
|
392
|
+
statusCode: cnt.statusCode
|
|
393
|
+
});
|
|
394
|
+
callback(null, result);
|
|
395
|
+
});
|
|
396
|
+
}
|
|
397
|
+
function _historyReadRawModify(context, historyReadRawModifiedDetails, indexRange, dataEncoding, continuationData, callback) {
|
|
398
|
+
const node = this;
|
|
399
|
+
(0, node_opcua_assert_1.assert)(historyReadRawModifiedDetails instanceof node_opcua_service_history_1.ReadRawModifiedDetails);
|
|
400
|
+
if (!historyReadRawModifiedDetails.isReadModified) {
|
|
401
|
+
return node._historyReadRaw(context, historyReadRawModifiedDetails, indexRange, dataEncoding, continuationData, callback);
|
|
402
|
+
}
|
|
403
|
+
else {
|
|
404
|
+
return node._historyReadModify(context, historyReadRawModifiedDetails, indexRange, dataEncoding, continuationData, callback);
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
function _historyRead(context, historyReadDetails, indexRange, dataEncoding, continuationData, callback) {
|
|
408
|
+
(0, node_opcua_assert_1.assert)(typeof callback === 'function');
|
|
409
|
+
if (historyReadDetails instanceof node_opcua_service_history_1.ReadRawModifiedDetails) {
|
|
410
|
+
// note: only ReadRawModifiedDetails supported at this time
|
|
411
|
+
return this._historyReadRawModify(context, historyReadDetails, indexRange, dataEncoding, continuationData, callback);
|
|
412
|
+
}
|
|
413
|
+
else if (historyReadDetails instanceof node_opcua_service_history_1.ReadEventDetails) {
|
|
414
|
+
// The ReadEventDetails structure is used to read the Events from the history database for the
|
|
415
|
+
// specified time domain for one or more HistoricalEventNodes. The Events are filtered based on
|
|
416
|
+
// the filter structure provided. This filter includes the EventFields that are to be returned. For a
|
|
417
|
+
// complete description of filter refer to Part 4.
|
|
418
|
+
// The startTime and endTime are used to filter on the Time field for Events.
|
|
419
|
+
// The time domain of the request is defined by startTime, endTime, and numValuesPerNode; at
|
|
420
|
+
// least two of these shall be specified. If endTime is less than startTime, or endTime and
|
|
421
|
+
// numValuesPerNode alone are specified then the data will be returned in reverse order with
|
|
422
|
+
// later/newer data provided first as if time were flowing backward. If all three are specified then
|
|
423
|
+
// the call shall return up to numValuesPerNode results going from startTime to endTime, in
|
|
424
|
+
// either ascending or descending order depending on the relative values of startTime and
|
|
425
|
+
// endTime. If numValuesPerNode is 0 then all of the values in the range are returned. The
|
|
426
|
+
// default value is used to indicate when startTime, endTime or numValuesPerNode are not
|
|
427
|
+
// specified.
|
|
428
|
+
// It is specifically allowed for the startTime and the endTime to be identical. This allows the
|
|
429
|
+
// Client to request the Event at a single instance in time. When the startTime and endTime are
|
|
430
|
+
// identical then time is presumed to be flowing forward. If no data exists at the time specified
|
|
431
|
+
// then the Server shall return the Good_NoData StatusCode.
|
|
432
|
+
// If a startTime, endTime and numValuesPerNode are all provided, and if more than
|
|
433
|
+
// numValuesPerNode Events exist within that time range for a given Node, then only
|
|
434
|
+
// numValuesPerNode Events per Node are returned along with a ContinuationPoint. When a
|
|
435
|
+
// ContinuationPoint is returned, a Client wanting the next numValuesPerNode values should
|
|
436
|
+
// call HistoryRead again with the continuationPoint set.
|
|
437
|
+
// If the request takes a long time to process then the Server can return partial results with a
|
|
438
|
+
// ContinuationPoint. This might be done if the request is going to take more time than the Client
|
|
439
|
+
// timeout hint. It may take longer than the Client timeout hint to retrieve any results. In this case
|
|
440
|
+
// the Server may return zero results with a ContinuationPoint that allows the Server to resume
|
|
441
|
+
// the calculation on the next Client HistoryRead call.
|
|
442
|
+
// For an interval in which no data exists, the corresponding StatusCode shall be Good_NoData.
|
|
443
|
+
// The filter parameter is used to determine which historical Events and their corresponding
|
|
444
|
+
// fields are returned. It is possible that the fields of an EventType are available for real time
|
|
445
|
+
// updating, but not available from the historian. In this case a StatusCode value will be returned
|
|
446
|
+
// for any Event field that cannot be returned. The value of the StatusCode shall be
|
|
447
|
+
// Bad_NoData.
|
|
448
|
+
// If the requested TimestampsToReturn is not supported for a Node then the operation shall
|
|
449
|
+
// return the Bad_TimestampNotSupported StatusCode. When reading Events this only applies
|
|
450
|
+
// to Event fields that are of type DataValue.
|
|
451
|
+
// todo provide correct implementation
|
|
452
|
+
const result = new node_opcua_service_history_1.HistoryReadResult({
|
|
453
|
+
historyData: new node_opcua_service_history_1.HistoryData({ dataValues: [] }),
|
|
454
|
+
statusCode: node_opcua_status_code_1.StatusCodes.BadHistoryOperationUnsupported
|
|
455
|
+
});
|
|
456
|
+
return callback(null, result);
|
|
457
|
+
}
|
|
458
|
+
else if (historyReadDetails instanceof node_opcua_service_history_1.ReadProcessedDetails) {
|
|
459
|
+
const addressSpace = this.addressSpace;
|
|
460
|
+
if (!addressSpace._readProcessedDetails) {
|
|
461
|
+
const result = new node_opcua_service_history_1.HistoryReadResult({
|
|
462
|
+
historyData: new node_opcua_service_history_1.HistoryData({}),
|
|
463
|
+
statusCode: node_opcua_status_code_1.StatusCodes.BadHistoryOperationUnsupported
|
|
464
|
+
});
|
|
465
|
+
return callback(null, result);
|
|
466
|
+
}
|
|
467
|
+
else {
|
|
468
|
+
return addressSpace._readProcessedDetails(this, context, historyReadDetails, indexRange, dataEncoding, continuationData, callback);
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
else if (historyReadDetails instanceof node_opcua_service_history_1.ReadAtTimeDetails) {
|
|
472
|
+
// Release 1.03 28 OPC Unified Architecture, Part 11
|
|
473
|
+
// The ReadAtTimeDetails structure reads the values and qualities from the history database for
|
|
474
|
+
// the specified timestamps for one or more HistoricalDataNodes. This function is intended to
|
|
475
|
+
// provide values to correlate with other values with a known timestamp. For example, a Client
|
|
476
|
+
// may need to read the values of sensors when lab samples were collected.
|
|
477
|
+
// The order of the values and qualities returned shall match the order of the timestamps
|
|
478
|
+
// supplied in the request.
|
|
479
|
+
// When no value exists for a specified timestamp, a value shall be Interpolated from the
|
|
480
|
+
// surrounding values to represent the value at the specified timestamp. The interpolation will
|
|
481
|
+
// follow the same rules as the standard Interpolated Aggregate as outlined in Part 13.
|
|
482
|
+
// If the useSimpleBounds flag is True and Interpolation is required then simple bounding values
|
|
483
|
+
// will be used to calculate the data value. If useSimpleBounds is False and Interpolation is
|
|
484
|
+
// required then interpolated bounding values will be used to calculate the data value. See
|
|
485
|
+
// Part 13 for the definition of simple bounding values and interpolated bounding values.
|
|
486
|
+
// If a value is found for the specified timestamp, then the Server will set the StatusCode
|
|
487
|
+
// InfoBits to be Raw. If the value is Interpolated from the surrounding values, then the Server
|
|
488
|
+
// will set the StatusCode InfoBits to be Interpolated.
|
|
489
|
+
// If the read request is taking a long time to calculate then the Server may return zero results
|
|
490
|
+
// with a ContinuationPoint that allows the Server to resume the calculation on the next Client
|
|
491
|
+
// HistoryRead call.
|
|
492
|
+
// If the requested TimestampsToReturn is not supported for a Node, then the operation shall
|
|
493
|
+
// return the Bad_TimestampNotSupported StatusCode.
|
|
494
|
+
// todo provide correct implementation
|
|
495
|
+
const result = new node_opcua_service_history_1.HistoryReadResult({
|
|
496
|
+
historyData: new node_opcua_service_history_1.HistoryData({ dataValues: [] }),
|
|
497
|
+
statusCode: node_opcua_status_code_1.StatusCodes.BadHistoryOperationUnsupported
|
|
498
|
+
});
|
|
499
|
+
return callback(null, result);
|
|
500
|
+
}
|
|
501
|
+
else {
|
|
502
|
+
const result = new node_opcua_service_history_1.HistoryReadResult({
|
|
503
|
+
historyData: new node_opcua_service_history_1.HistoryData({ dataValues: [] }),
|
|
504
|
+
statusCode: node_opcua_status_code_1.StatusCodes.BadHistoryOperationUnsupported
|
|
505
|
+
});
|
|
506
|
+
return callback(null, result);
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
function on_value_change(newDataValue) {
|
|
510
|
+
this._historyPush.call(this, newDataValue);
|
|
511
|
+
}
|
|
512
|
+
/**
|
|
513
|
+
* @method installHistoricalDataNode
|
|
514
|
+
* @param node UAVariable
|
|
515
|
+
* @param [options] {Object}
|
|
516
|
+
* @param [options.maxOnlineValues = 1000]
|
|
517
|
+
*/
|
|
518
|
+
function AddressSpace_installHistoricalDataNode(node, options) {
|
|
519
|
+
var _a, _b, _c;
|
|
520
|
+
address_space_ts_1.AddressSpace.historizerFactory = address_space_ts_1.AddressSpace.historizerFactory || {
|
|
521
|
+
create(node1, options1) {
|
|
522
|
+
return new VariableHistorian(node1, options1);
|
|
523
|
+
}
|
|
524
|
+
};
|
|
525
|
+
(0, node_opcua_assert_1.assert)(node.nodeClass === node_opcua_data_model_1.NodeClass.Variable);
|
|
526
|
+
options = options || {};
|
|
527
|
+
const addressSpace = node.addressSpace;
|
|
528
|
+
// install specific history behavior
|
|
529
|
+
node._historyRead = _historyRead;
|
|
530
|
+
node._historyPush = _historyPush;
|
|
531
|
+
node._historyReadRawModify = _historyReadRawModify;
|
|
532
|
+
node._historyReadModify = _historyReadModify;
|
|
533
|
+
node._historyReadRaw = _historyReadRaw;
|
|
534
|
+
node._historyReadRawAsync = _historyReadRawAsync;
|
|
535
|
+
node.varHistorian = options.historian || address_space_ts_1.AddressSpace.historizerFactory.create(node, options);
|
|
536
|
+
const historicalDataConfigurationType = addressSpace.findObjectType("HistoricalDataConfigurationType");
|
|
537
|
+
if (!historicalDataConfigurationType) {
|
|
538
|
+
throw new Error("cannot find HistoricalDataConfigurationType");
|
|
539
|
+
}
|
|
540
|
+
node.historizing = true;
|
|
541
|
+
// tslint:disable:no-bitwise
|
|
542
|
+
node.accessLevel = node.accessLevel | node_opcua_data_model_1.AccessLevelFlag.CurrentRead | node_opcua_data_model_1.AccessLevelFlag.HistoryRead;
|
|
543
|
+
if (node.userAccessLevel !== undefined) {
|
|
544
|
+
node.userAccessLevel = node.userAccessLevel | node_opcua_data_model_1.AccessLevelFlag.CurrentRead | node_opcua_data_model_1.AccessLevelFlag.HistoryRead;
|
|
545
|
+
}
|
|
546
|
+
const optionals = ["Stepped", "Definition", "MaxTimeInterval", "MinTimeInterval", "StartOfArchive", "StartOfOnlineArchive"];
|
|
547
|
+
// Note from spec : If a HistoricalDataNode has configuration defined then one
|
|
548
|
+
// instance shall have a BrowseName of ‘HA Configuration’
|
|
549
|
+
const historicalDataConfiguration = historicalDataConfigurationType.instantiate({
|
|
550
|
+
browseName: { name: "HA Configuration", namespaceIndex: 0 },
|
|
551
|
+
optionals
|
|
552
|
+
});
|
|
553
|
+
// All Historical Configuration Objects shall be referenced using the HasHistoricalConfiguration ReferenceType.
|
|
554
|
+
node.addReference({
|
|
555
|
+
isForward: true,
|
|
556
|
+
nodeId: historicalDataConfiguration.nodeId,
|
|
557
|
+
referenceType: "HasHistoricalConfiguration"
|
|
558
|
+
});
|
|
559
|
+
// The Stepped Variable specifies whether the historical data was collected in such a manner
|
|
560
|
+
// that it should be displayed as SlopedInterpolation (sloped line between points) or as
|
|
561
|
+
// SteppedInterpolation (vertically-connected horizontal lines between points) when raw data is
|
|
562
|
+
// examined. This Property also effects how some Aggregates are calculated. A value of True
|
|
563
|
+
// indicates the stepped interpolation mode. A value of False indicates SlopedInterpolation
|
|
564
|
+
// mode. The default value is False.
|
|
565
|
+
historicalDataConfiguration.stepped.setValueFromSource({ dataType: "Boolean", value: false });
|
|
566
|
+
// The MaxTimeInterval Variable specifies the maximum interval between data points in the
|
|
567
|
+
// history repository regardless of their value change (see Part 3 for definition of Duration).
|
|
568
|
+
(_a = historicalDataConfiguration.maxTimeInterval) === null || _a === void 0 ? void 0 : _a.setValueFromSource({ dataType: "Duration", value: 10 * 1000 });
|
|
569
|
+
// The MinTimeInterval Variable specifies the minimum interval between data points in the
|
|
570
|
+
// history repository regardless of their value change
|
|
571
|
+
(_b = historicalDataConfiguration.minTimeInterval) === null || _b === void 0 ? void 0 : _b.setValueFromSource({ dataType: "Duration", value: 0.1 * 1000 });
|
|
572
|
+
// The StartOfArchive Variable specifies the date before which there is no data in the archive
|
|
573
|
+
// either online or offline.
|
|
574
|
+
// The StartOfOnlineArchive Variable specifies the date of the earliest data in the online archive.
|
|
575
|
+
const startOfOnlineArchive = new Date();
|
|
576
|
+
(_c = historicalDataConfiguration.startOfOnlineArchive) === null || _c === void 0 ? void 0 : _c.setValueFromSource({
|
|
577
|
+
dataType: node_opcua_variant_1.DataType.DateTime,
|
|
578
|
+
value: startOfOnlineArchive
|
|
579
|
+
});
|
|
580
|
+
// TreatUncertainAsBad
|
|
581
|
+
// The TreatUncertainAsBad Variable indicates how the Server treats data returned with a
|
|
582
|
+
// StatusCode severity Uncertain with respect to Aggregate calculations. A value of True indicates
|
|
583
|
+
// the Server considers the severity equivalent to Bad, a value of False indicates the Server
|
|
584
|
+
// considers the severity equivalent to Good, unless the Aggregate definition says otherwise. The
|
|
585
|
+
// default value is True. Note that the value is still treated as Uncertain when the StatusCode for
|
|
586
|
+
// the result is calculated.
|
|
587
|
+
historicalDataConfiguration.aggregateConfiguration.treatUncertainAsBad.setValueFromSource({
|
|
588
|
+
dataType: "Boolean",
|
|
589
|
+
value: true
|
|
590
|
+
});
|
|
591
|
+
// The PercentDataBad Variable indicates the minimum percentage of Bad data in a given interval required for the
|
|
592
|
+
// StatusCode for the given interval for processed data request to be set to Bad.
|
|
593
|
+
// (Uncertain is treated as defined above.) Refer to 5.4.3 for details on using this Variable when assigning
|
|
594
|
+
// StatusCodes. For details on which Aggregates use the PercentDataBad Variable, see
|
|
595
|
+
// the definition of each Aggregate. The default value is 100.
|
|
596
|
+
historicalDataConfiguration.aggregateConfiguration.percentDataBad.setValueFromSource({
|
|
597
|
+
dataType: "Byte",
|
|
598
|
+
value: 100
|
|
599
|
+
});
|
|
600
|
+
// The PercentDataGood Variable indicates the minimum percentage of Good data in a given
|
|
601
|
+
// interval required for the StatusCode for the given interval for the processed data requests to be
|
|
602
|
+
// set to Good. Refer to 5.4.3 for details on using this Variable when assigning StatusCodes. For
|
|
603
|
+
// details on which Aggregates use the PercentDataGood Variable, see the definition of each
|
|
604
|
+
// Aggregate. The default value is 100.
|
|
605
|
+
historicalDataConfiguration.aggregateConfiguration.percentDataGood.setValueFromSource({
|
|
606
|
+
dataType: "Byte",
|
|
607
|
+
value: 100
|
|
608
|
+
});
|
|
609
|
+
//
|
|
610
|
+
// The PercentDataGood and PercentDataBad shall follow the following relationship
|
|
611
|
+
// PercentDataGood ≥ (100 – PercentDataBad). If they are equal the result of the
|
|
612
|
+
// PercentDataGood calculation is used. If the values entered for PercentDataGood and
|
|
613
|
+
//
|
|
614
|
+
// PercentDataBad do not result in a valid calculation (e.g. Bad = 80; Good = 0) the result will
|
|
615
|
+
// have a StatusCode of Bad_AggregateInvalidInputs The StatusCode
|
|
616
|
+
//
|
|
617
|
+
// Bad_AggregateInvalidInputs will be returned if the value of PercentDataGood or
|
|
618
|
+
// PercentDataBad exceed 100.
|
|
619
|
+
node.$historicalDataConfiguration = historicalDataConfiguration;
|
|
620
|
+
const dataValue = node.readValue();
|
|
621
|
+
if (dataValue.statusCode !== node_opcua_status_code_1.StatusCodes.BadWaitingForInitialData &&
|
|
622
|
+
dataValue.statusCode !== node_opcua_status_code_1.StatusCodes.UncertainInitialValue) {
|
|
623
|
+
on_value_change.call(node, dataValue);
|
|
624
|
+
}
|
|
625
|
+
node.on("value_changed", on_value_change);
|
|
626
|
+
// update the index of historizing nodes in the addressSpace
|
|
627
|
+
node.addressSpace.historizingNodes = node.addressSpace.historizingNodes || {};
|
|
628
|
+
node.addressSpace.historizingNodes[node.nodeId.toString()] = node;
|
|
629
|
+
}
|
|
630
|
+
exports.AddressSpace_installHistoricalDataNode = AddressSpace_installHistoricalDataNode;
|
|
631
631
|
//# sourceMappingURL=address_space_historical_data_node.js.map
|