node-opcua-address-space 2.96.0 → 2.98.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/package.json +37 -37
- package/source/interfaces/alarms_and_conditions/ua_condition_ex.ts +4 -3
- package/source/loader/make_xml_extension_object_parser.ts +10 -9
- package/src/address_space.ts +6 -5
- package/src/alarms_and_conditions/ua_condition_impl.ts +14 -9
- package/src/base_node_impl.ts +6 -2
- package/src/base_node_private.ts +73 -28
- package/src/data_access/ua_two_state_discrete_impl.ts +2 -0
- package/src/ua_variable_impl.ts +2039 -2037
- package/src/ua_variable_type_impl.ts +35 -17
- package/dist/source/address_space_ts.d.ts +0 -118
- package/dist/source/address_space_ts.js +0 -18
- package/dist/source/address_space_ts.js.map +0 -1
- package/dist/source/continuation_points/continuation_point_manager.d.ts +0 -91
- package/dist/source/continuation_points/continuation_point_manager.js +0 -201
- package/dist/source/continuation_points/continuation_point_manager.js.map +0 -1
- package/dist/source/helpers/adjust_browse_direction.d.ts +0 -5
- package/dist/source/helpers/adjust_browse_direction.js +0 -12
- package/dist/source/helpers/adjust_browse_direction.js.map +0 -1
- package/dist/source/helpers/argument_list.d.ts +0 -33
- package/dist/source/helpers/argument_list.js +0 -255
- package/dist/source/helpers/argument_list.js.map +0 -1
- package/dist/source/helpers/call_helpers.d.ts +0 -6
- package/dist/source/helpers/call_helpers.js +0 -72
- package/dist/source/helpers/call_helpers.js.map +0 -1
- package/dist/source/helpers/coerce_enum_value.d.ts +0 -6
- package/dist/source/helpers/coerce_enum_value.js +0 -34
- package/dist/source/helpers/coerce_enum_value.js.map +0 -1
- package/dist/source/helpers/dump_tools.d.ts +0 -14
- package/dist/source/helpers/dump_tools.js +0 -79
- package/dist/source/helpers/dump_tools.js.map +0 -1
- package/dist/source/helpers/ensure_secure_access.d.ts +0 -9
- package/dist/source/helpers/ensure_secure_access.js +0 -77
- package/dist/source/helpers/ensure_secure_access.js.map +0 -1
- package/dist/source/helpers/make_optionals_map.d.ts +0 -21
- package/dist/source/helpers/make_optionals_map.js +0 -30
- package/dist/source/helpers/make_optionals_map.js.map +0 -1
- package/dist/source/helpers/multiform_func.d.ts +0 -11
- package/dist/source/helpers/multiform_func.js +0 -76
- package/dist/source/helpers/multiform_func.js.map +0 -1
- package/dist/source/helpers/resolve_opaque_on_address_space.d.ts +0 -3
- package/dist/source/helpers/resolve_opaque_on_address_space.js +0 -37
- package/dist/source/helpers/resolve_opaque_on_address_space.js.map +0 -1
- package/dist/source/index.d.ts +0 -61
- package/dist/source/index.js +0 -90
- package/dist/source/index.js.map +0 -1
- package/dist/source/interfaces/alarms_and_conditions/condition_info_i.d.ts +0 -19
- package/dist/source/interfaces/alarms_and_conditions/condition_info_i.js +0 -3
- package/dist/source/interfaces/alarms_and_conditions/condition_info_i.js.map +0 -1
- package/dist/source/interfaces/alarms_and_conditions/condition_snapshot.d.ts +0 -193
- package/dist/source/interfaces/alarms_and_conditions/condition_snapshot.js +0 -3
- package/dist/source/interfaces/alarms_and_conditions/condition_snapshot.js.map +0 -1
- package/dist/source/interfaces/alarms_and_conditions/deviation_stuff.d.ts +0 -12
- package/dist/source/interfaces/alarms_and_conditions/deviation_stuff.js +0 -3
- package/dist/source/interfaces/alarms_and_conditions/deviation_stuff.js.map +0 -1
- package/dist/source/interfaces/alarms_and_conditions/install_setpoint_options.d.ts +0 -10
- package/dist/source/interfaces/alarms_and_conditions/install_setpoint_options.js +0 -3
- package/dist/source/interfaces/alarms_and_conditions/install_setpoint_options.js.map +0 -1
- package/dist/source/interfaces/alarms_and_conditions/instantiate_alarm_condition_options.d.ts +0 -7
- package/dist/source/interfaces/alarms_and_conditions/instantiate_alarm_condition_options.js +0 -3
- package/dist/source/interfaces/alarms_and_conditions/instantiate_alarm_condition_options.js.map +0 -1
- package/dist/source/interfaces/alarms_and_conditions/instantiate_condition_options.d.ts +0 -7
- package/dist/source/interfaces/alarms_and_conditions/instantiate_condition_options.js +0 -3
- package/dist/source/interfaces/alarms_and_conditions/instantiate_condition_options.js.map +0 -1
- package/dist/source/interfaces/alarms_and_conditions/instantiate_exclusive_deviation_alarm_options.d.ts +0 -4
- package/dist/source/interfaces/alarms_and_conditions/instantiate_exclusive_deviation_alarm_options.js +0 -3
- package/dist/source/interfaces/alarms_and_conditions/instantiate_exclusive_deviation_alarm_options.js.map +0 -1
- package/dist/source/interfaces/alarms_and_conditions/instantiate_exclusive_limit_alarm_options.d.ts +0 -4
- package/dist/source/interfaces/alarms_and_conditions/instantiate_exclusive_limit_alarm_options.js +0 -3
- package/dist/source/interfaces/alarms_and_conditions/instantiate_exclusive_limit_alarm_options.js.map +0 -1
- package/dist/source/interfaces/alarms_and_conditions/instantiate_limit_alarm_options.d.ts +0 -9
- package/dist/source/interfaces/alarms_and_conditions/instantiate_limit_alarm_options.js +0 -3
- package/dist/source/interfaces/alarms_and_conditions/instantiate_limit_alarm_options.js.map +0 -1
- package/dist/source/interfaces/alarms_and_conditions/instantiate_non_exclusive_deviation_alarm_options.d.ts +0 -4
- package/dist/source/interfaces/alarms_and_conditions/instantiate_non_exclusive_deviation_alarm_options.js +0 -3
- package/dist/source/interfaces/alarms_and_conditions/instantiate_non_exclusive_deviation_alarm_options.js.map +0 -1
- package/dist/source/interfaces/alarms_and_conditions/instantiate_non_exclusive_limit_alarm_options.d.ts +0 -4
- package/dist/source/interfaces/alarms_and_conditions/instantiate_non_exclusive_limit_alarm_options.js +0 -3
- package/dist/source/interfaces/alarms_and_conditions/instantiate_non_exclusive_limit_alarm_options.js.map +0 -1
- package/dist/source/interfaces/alarms_and_conditions/instantiate_off_normal_alarm_options.d.ts +0 -20
- package/dist/source/interfaces/alarms_and_conditions/instantiate_off_normal_alarm_options.js +0 -3
- package/dist/source/interfaces/alarms_and_conditions/instantiate_off_normal_alarm_options.js.map +0 -1
- package/dist/source/interfaces/alarms_and_conditions/ua_acknowledgeable_condition_ex.d.ts +0 -23
- package/dist/source/interfaces/alarms_and_conditions/ua_acknowledgeable_condition_ex.js +0 -3
- package/dist/source/interfaces/alarms_and_conditions/ua_acknowledgeable_condition_ex.js.map +0 -1
- package/dist/source/interfaces/alarms_and_conditions/ua_alarm_condition_ex.d.ts +0 -32
- package/dist/source/interfaces/alarms_and_conditions/ua_alarm_condition_ex.js +0 -3
- package/dist/source/interfaces/alarms_and_conditions/ua_alarm_condition_ex.js.map +0 -1
- package/dist/source/interfaces/alarms_and_conditions/ua_certificate_expiration_alarm_ex.d.ts +0 -19
- package/dist/source/interfaces/alarms_and_conditions/ua_certificate_expiration_alarm_ex.js +0 -3
- package/dist/source/interfaces/alarms_and_conditions/ua_certificate_expiration_alarm_ex.js.map +0 -1
- package/dist/source/interfaces/alarms_and_conditions/ua_condition_ex.d.ts +0 -42
- package/dist/source/interfaces/alarms_and_conditions/ua_condition_ex.js +0 -3
- package/dist/source/interfaces/alarms_and_conditions/ua_condition_ex.js.map +0 -1
- package/dist/source/interfaces/alarms_and_conditions/ua_discrete_alarm_ex.d.ts +0 -7
- package/dist/source/interfaces/alarms_and_conditions/ua_discrete_alarm_ex.js +0 -26
- package/dist/source/interfaces/alarms_and_conditions/ua_discrete_alarm_ex.js.map +0 -1
- package/dist/source/interfaces/alarms_and_conditions/ua_exclusive_deviation_alarm_ex.d.ts +0 -5
- package/dist/source/interfaces/alarms_and_conditions/ua_exclusive_deviation_alarm_ex.js +0 -3
- package/dist/source/interfaces/alarms_and_conditions/ua_exclusive_deviation_alarm_ex.js.map +0 -1
- package/dist/source/interfaces/alarms_and_conditions/ua_exclusive_limit_alarm_ex.d.ts +0 -20
- package/dist/source/interfaces/alarms_and_conditions/ua_exclusive_limit_alarm_ex.js +0 -3
- package/dist/source/interfaces/alarms_and_conditions/ua_exclusive_limit_alarm_ex.js.map +0 -1
- package/dist/source/interfaces/alarms_and_conditions/ua_limit_alarm_ex.d.ts +0 -26
- package/dist/source/interfaces/alarms_and_conditions/ua_limit_alarm_ex.js +0 -3
- package/dist/source/interfaces/alarms_and_conditions/ua_limit_alarm_ex.js.map +0 -1
- package/dist/source/interfaces/alarms_and_conditions/ua_non_exclusive_deviation_alarm_ex.d.ts +0 -8
- package/dist/source/interfaces/alarms_and_conditions/ua_non_exclusive_deviation_alarm_ex.js +0 -3
- package/dist/source/interfaces/alarms_and_conditions/ua_non_exclusive_deviation_alarm_ex.js.map +0 -1
- package/dist/source/interfaces/alarms_and_conditions/ua_non_exclusive_limit_alarm_ex.d.ts +0 -10
- package/dist/source/interfaces/alarms_and_conditions/ua_non_exclusive_limit_alarm_ex.js +0 -3
- package/dist/source/interfaces/alarms_and_conditions/ua_non_exclusive_limit_alarm_ex.js.map +0 -1
- package/dist/source/interfaces/data_access/ua_multistate_discrete_ex.d.ts +0 -21
- package/dist/source/interfaces/data_access/ua_multistate_discrete_ex.js +0 -3
- package/dist/source/interfaces/data_access/ua_multistate_discrete_ex.js.map +0 -1
- package/dist/source/interfaces/data_access/ua_multistate_value_discrete_ex.d.ts +0 -24
- package/dist/source/interfaces/data_access/ua_multistate_value_discrete_ex.js +0 -3
- package/dist/source/interfaces/data_access/ua_multistate_value_discrete_ex.js.map +0 -1
- package/dist/source/interfaces/data_access/ua_two_state_discrete_ex.d.ts +0 -12
- package/dist/source/interfaces/data_access/ua_two_state_discrete_ex.js +0 -3
- package/dist/source/interfaces/data_access/ua_two_state_discrete_ex.js.map +0 -1
- package/dist/source/interfaces/data_access/ua_y_array_item_ex.d.ts +0 -8
- package/dist/source/interfaces/data_access/ua_y_array_item_ex.js +0 -3
- package/dist/source/interfaces/data_access/ua_y_array_item_ex.js.map +0 -1
- package/dist/source/interfaces/extension_object_constructor.d.ts +0 -10
- package/dist/source/interfaces/extension_object_constructor.js +0 -3
- package/dist/source/interfaces/extension_object_constructor.js.map +0 -1
- package/dist/source/interfaces/nodeset_loader_options.d.ts +0 -4
- package/dist/source/interfaces/nodeset_loader_options.js +0 -3
- package/dist/source/interfaces/nodeset_loader_options.js.map +0 -1
- package/dist/source/interfaces/state_machine/ua_exclusive_limit_state_machine_type_ex.d.ts +0 -12
- package/dist/source/interfaces/state_machine/ua_exclusive_limit_state_machine_type_ex.js +0 -3
- package/dist/source/interfaces/state_machine/ua_exclusive_limit_state_machine_type_ex.js.map +0 -1
- package/dist/source/interfaces/state_machine/ua_finite_state_machine_type.d.ts +0 -49
- package/dist/source/interfaces/state_machine/ua_finite_state_machine_type.js +0 -3
- package/dist/source/interfaces/state_machine/ua_finite_state_machine_type.js.map +0 -1
- package/dist/source/interfaces/state_machine/ua_program_state_machine_type.d.ts +0 -11
- package/dist/source/interfaces/state_machine/ua_program_state_machine_type.js +0 -3
- package/dist/source/interfaces/state_machine/ua_program_state_machine_type.js.map +0 -1
- package/dist/source/interfaces/state_machine/ua_shelved_state_machine_ex.d.ts +0 -30
- package/dist/source/interfaces/state_machine/ua_shelved_state_machine_ex.js +0 -3
- package/dist/source/interfaces/state_machine/ua_shelved_state_machine_ex.js.map +0 -1
- package/dist/source/interfaces/state_machine/ua_state_machine_type.d.ts +0 -234
- package/dist/source/interfaces/state_machine/ua_state_machine_type.js +0 -3
- package/dist/source/interfaces/state_machine/ua_state_machine_type.js.map +0 -1
- package/dist/source/interfaces/state_machine/ua_transition_ex.d.ts +0 -6
- package/dist/source/interfaces/state_machine/ua_transition_ex.js +0 -3
- package/dist/source/interfaces/state_machine/ua_transition_ex.js.map +0 -1
- package/dist/source/interfaces/ua_subscription_diagnostics_variable_ex.d.ts +0 -8
- package/dist/source/interfaces/ua_subscription_diagnostics_variable_ex.js +0 -3
- package/dist/source/interfaces/ua_subscription_diagnostics_variable_ex.js.map +0 -1
- package/dist/source/loader/decode_xml_extension_object.d.ts +0 -6
- package/dist/source/loader/decode_xml_extension_object.js +0 -72
- package/dist/source/loader/decode_xml_extension_object.js.map +0 -1
- package/dist/source/loader/ensure_datatype_extracted.d.ts +0 -5
- package/dist/source/loader/ensure_datatype_extracted.js +0 -71
- package/dist/source/loader/ensure_datatype_extracted.js.map +0 -1
- package/dist/source/loader/generateAddressSpaceRaw.d.ts +0 -11
- package/dist/source/loader/generateAddressSpaceRaw.js +0 -46
- package/dist/source/loader/generateAddressSpaceRaw.js.map +0 -1
- package/dist/source/loader/load_nodeset2.d.ts +0 -17
- package/dist/source/loader/load_nodeset2.js +0 -1484
- package/dist/source/loader/load_nodeset2.js.map +0 -1
- package/dist/source/loader/make_semver_compatible.d.ts +0 -6
- package/dist/source/loader/make_semver_compatible.js +0 -26
- package/dist/source/loader/make_semver_compatible.js.map +0 -1
- package/dist/source/loader/make_xml_extension_object_parser.d.ts +0 -28
- package/dist/source/loader/make_xml_extension_object_parser.js +0 -326
- package/dist/source/loader/make_xml_extension_object_parser.js.map +0 -1
- package/dist/source/loader/namespace_post_step.d.ts +0 -10
- package/dist/source/loader/namespace_post_step.js +0 -62
- package/dist/source/loader/namespace_post_step.js.map +0 -1
- package/dist/source/loader/register_node_promoter.d.ts +0 -2
- package/dist/source/loader/register_node_promoter.js +0 -10
- package/dist/source/loader/register_node_promoter.js.map +0 -1
- package/dist/source/namespace.d.ts +0 -6
- package/dist/source/namespace.js +0 -3
- package/dist/source/namespace.js.map +0 -1
- package/dist/source/namespace_alarm_and_condition.d.ts +0 -32
- package/dist/source/namespace_alarm_and_condition.js +0 -3
- package/dist/source/namespace_alarm_and_condition.js.map +0 -1
- package/dist/source/namespace_data_access.d.ts +0 -42
- package/dist/source/namespace_data_access.js +0 -3
- package/dist/source/namespace_data_access.js.map +0 -1
- package/dist/source/namespace_machine_state.d.ts +0 -8
- package/dist/source/namespace_machine_state.js +0 -3
- package/dist/source/namespace_machine_state.js.map +0 -1
- package/dist/source/pseudo_session.d.ts +0 -72
- package/dist/source/pseudo_session.js +0 -255
- package/dist/source/pseudo_session.js.map +0 -1
- package/dist/source/session_context.d.ts +0 -111
- package/dist/source/session_context.js +0 -265
- package/dist/source/session_context.js.map +0 -1
- package/dist/source/set_namespace_meta_data.d.ts +0 -2
- package/dist/source/set_namespace_meta_data.js +0 -60
- package/dist/source/set_namespace_meta_data.js.map +0 -1
- package/dist/source/ua_root_folder.d.ts +0 -9
- package/dist/source/ua_root_folder.js +0 -3
- package/dist/source/ua_root_folder.js.map +0 -1
- package/dist/source/ua_two_state_variable_ex.d.ts +0 -23
- package/dist/source/ua_two_state_variable_ex.js +0 -3
- package/dist/source/ua_two_state_variable_ex.js.map +0 -1
- package/dist/source/xml_writer.d.ts +0 -18
- package/dist/source/xml_writer.js +0 -3
- package/dist/source/xml_writer.js.map +0 -1
- package/dist/src/address_space.d.ts +0 -387
- package/dist/src/address_space.js +0 -1385
- package/dist/src/address_space.js.map +0 -1
- package/dist/src/address_space_change_event_tools.d.ts +0 -6
- package/dist/src/address_space_change_event_tools.js +0 -153
- package/dist/src/address_space_change_event_tools.js.map +0 -1
- package/dist/src/address_space_private.d.ts +0 -43
- package/dist/src/address_space_private.js +0 -3
- package/dist/src/address_space_private.js.map +0 -1
- package/dist/src/alarms_and_conditions/condition.d.ts +0 -5
- package/dist/src/alarms_and_conditions/condition.js +0 -79
- package/dist/src/alarms_and_conditions/condition.js.map +0 -1
- package/dist/src/alarms_and_conditions/condition_info_impl.d.ts +0 -26
- package/dist/src/alarms_and_conditions/condition_info_impl.js +0 -55
- package/dist/src/alarms_and_conditions/condition_info_impl.js.map +0 -1
- package/dist/src/alarms_and_conditions/condition_snapshot_impl.d.ts +0 -222
- package/dist/src/alarms_and_conditions/condition_snapshot_impl.js +0 -658
- package/dist/src/alarms_and_conditions/condition_snapshot_impl.js.map +0 -1
- package/dist/src/alarms_and_conditions/deviation_alarm_helper.d.ts +0 -9
- package/dist/src/alarms_and_conditions/deviation_alarm_helper.js +0 -61
- package/dist/src/alarms_and_conditions/deviation_alarm_helper.js.map +0 -1
- package/dist/src/alarms_and_conditions/index.d.ts +0 -16
- package/dist/src/alarms_and_conditions/index.js +0 -33
- package/dist/src/alarms_and_conditions/index.js.map +0 -1
- package/dist/src/alarms_and_conditions/ua_acknowledgeable_condition_impl.d.ts +0 -44
- package/dist/src/alarms_and_conditions/ua_acknowledgeable_condition_impl.js +0 -245
- package/dist/src/alarms_and_conditions/ua_acknowledgeable_condition_impl.js.map +0 -1
- package/dist/src/alarms_and_conditions/ua_alarm_condition_impl.d.ts +0 -93
- package/dist/src/alarms_and_conditions/ua_alarm_condition_impl.js +0 -419
- package/dist/src/alarms_and_conditions/ua_alarm_condition_impl.js.map +0 -1
- package/dist/src/alarms_and_conditions/ua_base_event_impl.d.ts +0 -26
- package/dist/src/alarms_and_conditions/ua_base_event_impl.js +0 -39
- package/dist/src/alarms_and_conditions/ua_base_event_impl.js.map +0 -1
- package/dist/src/alarms_and_conditions/ua_certificate_expiration_alarm_impl.d.ts +0 -44
- package/dist/src/alarms_and_conditions/ua_certificate_expiration_alarm_impl.js +0 -184
- package/dist/src/alarms_and_conditions/ua_certificate_expiration_alarm_impl.js.map +0 -1
- package/dist/src/alarms_and_conditions/ua_condition_impl.d.ts +0 -153
- package/dist/src/alarms_and_conditions/ua_condition_impl.js +0 -1029
- package/dist/src/alarms_and_conditions/ua_condition_impl.js.map +0 -1
- package/dist/src/alarms_and_conditions/ua_discrete_alarm_impl.d.ts +0 -14
- package/dist/src/alarms_and_conditions/ua_discrete_alarm_impl.js +0 -35
- package/dist/src/alarms_and_conditions/ua_discrete_alarm_impl.js.map +0 -1
- package/dist/src/alarms_and_conditions/ua_exclusive_deviation_alarm_impl.d.ts +0 -24
- package/dist/src/alarms_and_conditions/ua_exclusive_deviation_alarm_impl.js +0 -57
- package/dist/src/alarms_and_conditions/ua_exclusive_deviation_alarm_impl.js.map +0 -1
- package/dist/src/alarms_and_conditions/ua_exclusive_level_alarm_impl.d.ts +0 -11
- package/dist/src/alarms_and_conditions/ua_exclusive_level_alarm_impl.js +0 -12
- package/dist/src/alarms_and_conditions/ua_exclusive_level_alarm_impl.js.map +0 -1
- package/dist/src/alarms_and_conditions/ua_exclusive_limit_alarm_impl.d.ts +0 -23
- package/dist/src/alarms_and_conditions/ua_exclusive_limit_alarm_impl.js +0 -87
- package/dist/src/alarms_and_conditions/ua_exclusive_limit_alarm_impl.js.map +0 -1
- package/dist/src/alarms_and_conditions/ua_exclusive_rate_of_change_alarm_impl.d.ts +0 -11
- package/dist/src/alarms_and_conditions/ua_exclusive_rate_of_change_alarm_impl.js +0 -8
- package/dist/src/alarms_and_conditions/ua_exclusive_rate_of_change_alarm_impl.js.map +0 -1
- package/dist/src/alarms_and_conditions/ua_limit_alarm_impl.d.ts +0 -79
- package/dist/src/alarms_and_conditions/ua_limit_alarm_impl.js +0 -251
- package/dist/src/alarms_and_conditions/ua_limit_alarm_impl.js.map +0 -1
- package/dist/src/alarms_and_conditions/ua_non_exclusive_deviation_alarm_impl.d.ts +0 -24
- package/dist/src/alarms_and_conditions/ua_non_exclusive_deviation_alarm_impl.js +0 -51
- package/dist/src/alarms_and_conditions/ua_non_exclusive_deviation_alarm_impl.js.map +0 -1
- package/dist/src/alarms_and_conditions/ua_non_exclusive_limit_alarm_impl.d.ts +0 -19
- package/dist/src/alarms_and_conditions/ua_non_exclusive_limit_alarm_impl.js +0 -163
- package/dist/src/alarms_and_conditions/ua_non_exclusive_limit_alarm_impl.js.map +0 -1
- package/dist/src/alarms_and_conditions/ua_off_normal_alarm_impl.d.ts +0 -46
- package/dist/src/alarms_and_conditions/ua_off_normal_alarm_impl.js +0 -166
- package/dist/src/alarms_and_conditions/ua_off_normal_alarm_impl.js.map +0 -1
- package/dist/src/alarms_and_conditions/ua_system_off_normal_alarm_impl.d.ts +0 -18
- package/dist/src/alarms_and_conditions/ua_system_off_normal_alarm_impl.js +0 -18
- package/dist/src/alarms_and_conditions/ua_system_off_normal_alarm_impl.js.map +0 -1
- package/dist/src/apply_condition_refresh.d.ts +0 -6
- package/dist/src/apply_condition_refresh.js +0 -28
- package/dist/src/apply_condition_refresh.js.map +0 -1
- package/dist/src/base_node_impl.d.ts +0 -283
- package/dist/src/base_node_impl.js +0 -1452
- package/dist/src/base_node_impl.js.map +0 -1
- package/dist/src/base_node_private.d.ts +0 -81
- package/dist/src/base_node_private.js +0 -804
- package/dist/src/base_node_private.js.map +0 -1
- package/dist/src/check_value_rank_compatibility.d.ts +0 -15
- package/dist/src/check_value_rank_compatibility.js +0 -82
- package/dist/src/check_value_rank_compatibility.js.map +0 -1
- package/dist/src/data_access/add_dataItem_stuff.d.ts +0 -11
- package/dist/src/data_access/add_dataItem_stuff.js +0 -62
- package/dist/src/data_access/add_dataItem_stuff.js.map +0 -1
- package/dist/src/data_access/check_variant_compatibility_ua_analog_item.d.ts +0 -1
- package/dist/src/data_access/check_variant_compatibility_ua_analog_item.js +0 -35
- package/dist/src/data_access/check_variant_compatibility_ua_analog_item.js.map +0 -1
- package/dist/src/data_access/ua_multistate_discrete_impl.d.ts +0 -32
- package/dist/src/data_access/ua_multistate_discrete_impl.js +0 -131
- package/dist/src/data_access/ua_multistate_discrete_impl.js.map +0 -1
- package/dist/src/data_access/ua_multistate_value_discrete_impl.d.ts +0 -52
- package/dist/src/data_access/ua_multistate_value_discrete_impl.js +0 -254
- package/dist/src/data_access/ua_multistate_value_discrete_impl.js.map +0 -1
- package/dist/src/data_access/ua_two_state_discrete_impl.d.ts +0 -25
- package/dist/src/data_access/ua_two_state_discrete_impl.js +0 -154
- package/dist/src/data_access/ua_two_state_discrete_impl.js.map +0 -1
- package/dist/src/event_data.d.ts +0 -34
- package/dist/src/event_data.js +0 -65
- package/dist/src/event_data.js.map +0 -1
- package/dist/src/extension_object_array_node.d.ts +0 -23
- package/dist/src/extension_object_array_node.js +0 -249
- package/dist/src/extension_object_array_node.js.map +0 -1
- package/dist/src/historical_access/address_space_historical_data_node.d.ts +0 -26
- package/dist/src/historical_access/address_space_historical_data_node.js +0 -653
- package/dist/src/historical_access/address_space_historical_data_node.js.map +0 -1
- package/dist/src/idx_iterator.d.ts +0 -8
- package/dist/src/idx_iterator.js +0 -51
- package/dist/src/idx_iterator.js.map +0 -1
- package/dist/src/index_current.d.ts +0 -46
- package/dist/src/index_current.js +0 -78
- package/dist/src/index_current.js.map +0 -1
- package/dist/src/namespace_impl.d.ts +0 -456
- package/dist/src/namespace_impl.js +0 -1763
- package/dist/src/namespace_impl.js.map +0 -1
- package/dist/src/namespace_private.d.ts +0 -23
- package/dist/src/namespace_private.js +0 -33
- package/dist/src/namespace_private.js.map +0 -1
- package/dist/src/nodeid_manager.d.ts +0 -37
- package/dist/src/nodeid_manager.js +0 -184
- package/dist/src/nodeid_manager.js.map +0 -1
- package/dist/src/nodeset_tools/adjust_namespace_array.d.ts +0 -2
- package/dist/src/nodeset_tools/adjust_namespace_array.js +0 -14
- package/dist/src/nodeset_tools/adjust_namespace_array.js.map +0 -1
- package/dist/src/nodeset_tools/construct_namespace_dependency.d.ts +0 -18
- package/dist/src/nodeset_tools/construct_namespace_dependency.js +0 -141
- package/dist/src/nodeset_tools/construct_namespace_dependency.js.map +0 -1
- package/dist/src/nodeset_tools/dump_to_bsd.d.ts +0 -2
- package/dist/src/nodeset_tools/dump_to_bsd.js +0 -164
- package/dist/src/nodeset_tools/dump_to_bsd.js.map +0 -1
- package/dist/src/nodeset_tools/nodeset_to_xml.d.ts +0 -10
- package/dist/src/nodeset_tools/nodeset_to_xml.js +0 -1288
- package/dist/src/nodeset_tools/nodeset_to_xml.js.map +0 -1
- package/dist/src/private_namespace.d.ts +0 -5
- package/dist/src/private_namespace.js +0 -20
- package/dist/src/private_namespace.js.map +0 -1
- package/dist/src/reference_impl.d.ts +0 -43
- package/dist/src/reference_impl.js +0 -140
- package/dist/src/reference_impl.js.map +0 -1
- package/dist/src/role_permissions.d.ts +0 -2
- package/dist/src/role_permissions.js +0 -11
- package/dist/src/role_permissions.js.map +0 -1
- package/dist/src/state_machine/finite_state_machine.d.ts +0 -81
- package/dist/src/state_machine/finite_state_machine.js +0 -389
- package/dist/src/state_machine/finite_state_machine.js.map +0 -1
- package/dist/src/state_machine/ua_shelving_state_machine_ex.d.ts +0 -38
- package/dist/src/state_machine/ua_shelving_state_machine_ex.js +0 -251
- package/dist/src/state_machine/ua_shelving_state_machine_ex.js.map +0 -1
- package/dist/src/state_machine/ua_two_state_variable.d.ts +0 -61
- package/dist/src/state_machine/ua_two_state_variable.js +0 -332
- package/dist/src/state_machine/ua_two_state_variable.js.map +0 -1
- package/dist/src/tool_isSubtypeOf.d.ts +0 -18
- package/dist/src/tool_isSubtypeOf.js +0 -125
- package/dist/src/tool_isSubtypeOf.js.map +0 -1
- package/dist/src/tool_isSupertypeOf.d.ts +0 -18
- package/dist/src/tool_isSupertypeOf.js +0 -125
- package/dist/src/tool_isSupertypeOf.js.map +0 -1
- package/dist/src/ua_condition_type.d.ts +0 -8
- package/dist/src/ua_condition_type.js +0 -3
- package/dist/src/ua_condition_type.js.map +0 -1
- package/dist/src/ua_data_type_impl.d.ts +0 -89
- package/dist/src/ua_data_type_impl.js +0 -369
- package/dist/src/ua_data_type_impl.js.map +0 -1
- package/dist/src/ua_method_impl.d.ts +0 -42
- package/dist/src/ua_method_impl.js +0 -218
- package/dist/src/ua_method_impl.js.map +0 -1
- package/dist/src/ua_object_impl.d.ts +0 -35
- package/dist/src/ua_object_impl.js +0 -169
- package/dist/src/ua_object_impl.js.map +0 -1
- package/dist/src/ua_object_type_impl.d.ts +0 -50
- package/dist/src/ua_object_type_impl.js +0 -127
- package/dist/src/ua_object_type_impl.js.map +0 -1
- package/dist/src/ua_reference_type_impl.d.ts +0 -45
- package/dist/src/ua_reference_type_impl.js +0 -142
- package/dist/src/ua_reference_type_impl.js.map +0 -1
- package/dist/src/ua_variable_impl.d.ts +0 -380
- package/dist/src/ua_variable_impl.js +0 -1738
- package/dist/src/ua_variable_impl.js.map +0 -1
- package/dist/src/ua_variable_impl_ext_obj.d.ts +0 -23
- package/dist/src/ua_variable_impl_ext_obj.js +0 -671
- package/dist/src/ua_variable_impl_ext_obj.js.map +0 -1
- package/dist/src/ua_variable_type_impl.d.ts +0 -74
- package/dist/src/ua_variable_type_impl.js +0 -582
- package/dist/src/ua_variable_type_impl.js.map +0 -1
- package/dist/src/ua_view_impl.d.ts +0 -19
- package/dist/src/ua_view_impl.js +0 -44
- package/dist/src/ua_view_impl.js.map +0 -1
- package/distHelpers/add_event_generator_object.d.ts +0 -3
- package/distHelpers/add_event_generator_object.js +0 -65
- package/distHelpers/add_event_generator_object.js.map +0 -1
- package/distHelpers/alarms_and_conditions_demo.d.ts +0 -9
- package/distHelpers/alarms_and_conditions_demo.js +0 -116
- package/distHelpers/alarms_and_conditions_demo.js.map +0 -1
- package/distHelpers/assertHasMatchingReference.d.ts +0 -19
- package/distHelpers/assertHasMatchingReference.js +0 -41
- package/distHelpers/assertHasMatchingReference.js.map +0 -1
- package/distHelpers/boiler_system.d.ts +0 -113
- package/distHelpers/boiler_system.js +0 -396
- package/distHelpers/boiler_system.js.map +0 -1
- package/distHelpers/create_minimalist_address_space_nodeset.d.ts +0 -5
- package/distHelpers/create_minimalist_address_space_nodeset.js +0 -172
- package/distHelpers/create_minimalist_address_space_nodeset.js.map +0 -1
- package/distHelpers/date_utils.d.ts +0 -3
- package/distHelpers/date_utils.js +0 -10
- package/distHelpers/date_utils.js.map +0 -1
- package/distHelpers/dump_statemachine.d.ts +0 -0
- package/distHelpers/dump_statemachine.js +0 -128
- package/distHelpers/dump_statemachine.js.map +0 -1
- package/distHelpers/get_address_space_fixture.d.ts +0 -1
- package/distHelpers/get_address_space_fixture.js +0 -31
- package/distHelpers/get_address_space_fixture.js.map +0 -1
- package/distHelpers/get_mini_address_space.d.ts +0 -7
- package/distHelpers/get_mini_address_space.js +0 -37
- package/distHelpers/get_mini_address_space.js.map +0 -1
- package/distHelpers/index.d.ts +0 -12
- package/distHelpers/index.js +0 -29
- package/distHelpers/index.js.map +0 -1
- package/distHelpers/mock_session.d.ts +0 -10
- package/distHelpers/mock_session.js +0 -26
- package/distHelpers/mock_session.js.map +0 -1
- package/distNodeJS/generate_address_space.d.ts +0 -6
- package/distNodeJS/generate_address_space.js +0 -53
- package/distNodeJS/generate_address_space.js.map +0 -1
- package/distNodeJS/index.d.ts +0 -1
- package/distNodeJS/index.js +0 -18
- package/distNodeJS/index.js.map +0 -1
- package/source/helpers/dump_tools.ts +0 -92
- package/src/nodeset_tools/dump_to_bsd.ts +0 -196
- package/test_helpers/dump_statemachine.ts +0 -155
package/src/ua_variable_impl.ts
CHANGED
|
@@ -1,2305 +1,2307 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
}
|
|
120
|
-
userAccessLevel = adjust_accessLevel(userAccessLevel);
|
|
121
|
-
accessLevel = adjust_accessLevel(accessLevel);
|
|
122
|
-
return makeAccessLevelFlag(accessLevel & userAccessLevel);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
function adjust_samplingInterval(minimumSamplingInterval: number): number {
|
|
126
|
-
assert(isFinite(minimumSamplingInterval));
|
|
127
|
-
if (minimumSamplingInterval < 0) {
|
|
128
|
-
return -1; // only -1 is a valid negative value for samplingInterval and means "unspecified"
|
|
129
|
-
}
|
|
130
|
-
return minimumSamplingInterval;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
function is_Variant(v: any): boolean {
|
|
134
|
-
return v instanceof Variant;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
function is_StatusCode(v: any): boolean {
|
|
138
|
-
return (
|
|
139
|
-
v &&
|
|
140
|
-
v.constructor &&
|
|
141
|
-
(
|
|
142
|
-
v instanceof StatusCode ||
|
|
143
|
-
v.constructor.name === "ConstantStatusCode" ||
|
|
144
|
-
v.constructor.name === "StatusCode" ||
|
|
145
|
-
v.constructor.name === "ModifiableStatusCode")
|
|
146
|
-
);
|
|
1
|
+
/* eslint-disable max-statements */
|
|
2
|
+
/* eslint-disable complexity */
|
|
3
|
+
/**
|
|
4
|
+
* @module node-opcua-address-space
|
|
5
|
+
*/
|
|
6
|
+
// tslint:disable:no-bitwise
|
|
7
|
+
// tslint:disable:no-console
|
|
8
|
+
// tslint:disable:max-line-length
|
|
9
|
+
import * as chalk from "chalk";
|
|
10
|
+
|
|
11
|
+
import {
|
|
12
|
+
BindExtensionObjectOptions,
|
|
13
|
+
CloneExtraInfo,
|
|
14
|
+
ContinuationData,
|
|
15
|
+
defaultCloneExtraInfo,
|
|
16
|
+
defaultCloneFilter,
|
|
17
|
+
GetFunc,
|
|
18
|
+
SetFunc,
|
|
19
|
+
VariableDataValueGetterSync,
|
|
20
|
+
VariableDataValueSetterWithCallback
|
|
21
|
+
} from "node-opcua-address-space-base";
|
|
22
|
+
import { assert } from "node-opcua-assert";
|
|
23
|
+
import {
|
|
24
|
+
isValidDataEncoding,
|
|
25
|
+
convertAccessLevelFlagToByte,
|
|
26
|
+
QualifiedNameLike,
|
|
27
|
+
NodeClass,
|
|
28
|
+
AccessLevelFlag,
|
|
29
|
+
makeAccessLevelFlag,
|
|
30
|
+
AttributeIds,
|
|
31
|
+
isDataEncoding,
|
|
32
|
+
QualifiedName
|
|
33
|
+
} from "node-opcua-data-model";
|
|
34
|
+
import { extractRange, sameDataValue, DataValue, DataValueLike, DataValueT } from "node-opcua-data-value";
|
|
35
|
+
import { coerceClock, getCurrentClock, PreciseClock } from "node-opcua-date-time";
|
|
36
|
+
import { checkDebugFlag, make_debugLog, make_errorLog, make_warningLog } from "node-opcua-debug";
|
|
37
|
+
import { ExtensionObject } from "node-opcua-extension-object";
|
|
38
|
+
import { NodeId } from "node-opcua-nodeid";
|
|
39
|
+
import { NumericRange } from "node-opcua-numeric-range";
|
|
40
|
+
import { WriteValue } from "node-opcua-service-write";
|
|
41
|
+
import { StatusCode, StatusCodes, CallbackT } from "node-opcua-status-code";
|
|
42
|
+
import {
|
|
43
|
+
HistoryReadDetails,
|
|
44
|
+
HistoryReadResult,
|
|
45
|
+
PermissionType,
|
|
46
|
+
ReadAtTimeDetails,
|
|
47
|
+
ReadEventDetails,
|
|
48
|
+
ReadProcessedDetails,
|
|
49
|
+
ReadRawModifiedDetails,
|
|
50
|
+
WriteValueOptions
|
|
51
|
+
} from "node-opcua-types";
|
|
52
|
+
import * as utils from "node-opcua-utils";
|
|
53
|
+
import {
|
|
54
|
+
Variant,
|
|
55
|
+
VariantLike,
|
|
56
|
+
DataType,
|
|
57
|
+
sameVariant,
|
|
58
|
+
VariantArrayType,
|
|
59
|
+
adjustVariant,
|
|
60
|
+
verifyRankAndDimensions
|
|
61
|
+
} from "node-opcua-variant";
|
|
62
|
+
import { StatusCodeCallback } from "node-opcua-status-code";
|
|
63
|
+
import {
|
|
64
|
+
IAddressSpace,
|
|
65
|
+
BindVariableOptions,
|
|
66
|
+
IVariableHistorian,
|
|
67
|
+
TimestampGetFunc,
|
|
68
|
+
TimestampSetFunc,
|
|
69
|
+
UADataType,
|
|
70
|
+
UAVariable,
|
|
71
|
+
UAVariableType,
|
|
72
|
+
CloneOptions,
|
|
73
|
+
CloneFilter,
|
|
74
|
+
ISessionContext,
|
|
75
|
+
BaseNode,
|
|
76
|
+
UAVariableT
|
|
77
|
+
} from "node-opcua-address-space-base";
|
|
78
|
+
import { UAHistoricalDataConfiguration } from "node-opcua-nodeset-ua";
|
|
79
|
+
|
|
80
|
+
import { SessionContext } from "../source/session_context";
|
|
81
|
+
import { convertToCallbackFunction1 } from "../source/helpers/multiform_func";
|
|
82
|
+
import { BaseNodeImpl, InternalBaseNodeOptions } from "./base_node_impl";
|
|
83
|
+
import { _clone, ToStringBuilder, UAVariable_toString } from "./base_node_private";
|
|
84
|
+
import { EnumerationInfo, IEnumItem, UADataTypeImpl } from "./ua_data_type_impl";
|
|
85
|
+
import { apply_condition_refresh, ConditionRefreshCache } from "./apply_condition_refresh";
|
|
86
|
+
import {
|
|
87
|
+
extractPartialData,
|
|
88
|
+
incrementElement,
|
|
89
|
+
propagateTouchValueDownward,
|
|
90
|
+
propagateTouchValueDownwardArray,
|
|
91
|
+
propagateTouchValueUpward,
|
|
92
|
+
setExtensionObjectPartialValue,
|
|
93
|
+
_bindExtensionObject,
|
|
94
|
+
_bindExtensionObjectArrayOrMatrix,
|
|
95
|
+
_installExtensionObjectBindingOnProperties,
|
|
96
|
+
_touchValue
|
|
97
|
+
} from "./ua_variable_impl_ext_obj";
|
|
98
|
+
|
|
99
|
+
const debugLog = make_debugLog(__filename);
|
|
100
|
+
const warningLog = make_warningLog(__filename);
|
|
101
|
+
const doDebug = checkDebugFlag(__filename);
|
|
102
|
+
const errorLog = make_errorLog(__filename);
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
export function adjust_accessLevel(accessLevel: string | number | null): AccessLevelFlag {
|
|
107
|
+
accessLevel = utils.isNullOrUndefined(accessLevel) ? "CurrentRead | CurrentWrite" : accessLevel;
|
|
108
|
+
accessLevel = makeAccessLevelFlag(accessLevel);
|
|
109
|
+
assert(isFinite(accessLevel));
|
|
110
|
+
return accessLevel;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export function adjust_userAccessLevel(
|
|
114
|
+
userAccessLevel: string | number | null | undefined,
|
|
115
|
+
accessLevel: string | number | null
|
|
116
|
+
): AccessLevelFlag | undefined {
|
|
117
|
+
if (userAccessLevel === undefined) {
|
|
118
|
+
return undefined;
|
|
147
119
|
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
120
|
+
userAccessLevel = adjust_accessLevel(userAccessLevel);
|
|
121
|
+
accessLevel = adjust_accessLevel(accessLevel);
|
|
122
|
+
return makeAccessLevelFlag(accessLevel & userAccessLevel);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function adjust_samplingInterval(minimumSamplingInterval: number): number {
|
|
126
|
+
assert(isFinite(minimumSamplingInterval));
|
|
127
|
+
if (minimumSamplingInterval < 0) {
|
|
128
|
+
return -1; // only -1 is a valid negative value for samplingInterval and means "unspecified"
|
|
129
|
+
}
|
|
130
|
+
return minimumSamplingInterval;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function is_Variant(v: any): boolean {
|
|
134
|
+
return v instanceof Variant;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function is_StatusCode(v: any): boolean {
|
|
138
|
+
return (
|
|
139
|
+
v &&
|
|
140
|
+
v.constructor &&
|
|
141
|
+
(
|
|
142
|
+
v instanceof StatusCode ||
|
|
143
|
+
v.constructor.name === "ConstantStatusCode" ||
|
|
144
|
+
v.constructor.name === "StatusCode" ||
|
|
145
|
+
v.constructor.name === "ModifiableStatusCode")
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function is_Variant_or_StatusCode(v: any): boolean {
|
|
150
|
+
if (is_Variant(v)) {
|
|
151
|
+
// /@@assert(v.isValid());
|
|
154
152
|
}
|
|
153
|
+
return is_Variant(v) || is_StatusCode(v);
|
|
154
|
+
}
|
|
155
155
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
156
|
+
function _dataType_toUADataType(addressSpace: IAddressSpace, dataType: DataType): UADataType {
|
|
157
|
+
assert(addressSpace);
|
|
158
|
+
assert(dataType !== DataType.Null);
|
|
159
159
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
}
|
|
165
|
-
return dataTypeNode as UADataType;
|
|
160
|
+
const dataTypeNode = addressSpace.findDataType(DataType[dataType]);
|
|
161
|
+
/* istanbul ignore next */
|
|
162
|
+
if (!dataTypeNode) {
|
|
163
|
+
throw new Error(" Cannot find DataType " + DataType[dataType] + " in address Space");
|
|
166
164
|
}
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
165
|
+
return dataTypeNode as UADataType;
|
|
166
|
+
}
|
|
167
|
+
/*=
|
|
168
|
+
*
|
|
169
|
+
* @param addressSpace
|
|
170
|
+
* @param dataTypeNodeId : the nodeId matching the dataType of the destination variable.
|
|
171
|
+
* @param variantDataType: the dataType of the variant to write to the destination variable
|
|
172
|
+
* @param nodeId
|
|
173
|
+
* @return {boolean} true if the variant dataType is compatible with the Variable DataType
|
|
174
|
+
*/
|
|
175
|
+
function validateDataType(
|
|
176
|
+
addressSpace: IAddressSpace,
|
|
177
|
+
dataTypeNodeId: NodeId,
|
|
178
|
+
variantDataType: DataType,
|
|
179
|
+
nodeId: NodeId,
|
|
180
|
+
allowNulls: boolean
|
|
181
|
+
): boolean {
|
|
182
|
+
if (variantDataType === DataType.ExtensionObject) {
|
|
183
|
+
return true;
|
|
184
|
+
}
|
|
185
|
+
if (variantDataType === DataType.Null && allowNulls) {
|
|
186
|
+
return true;
|
|
187
|
+
}
|
|
188
|
+
if (variantDataType === DataType.Null && !allowNulls) {
|
|
189
|
+
return false;
|
|
190
|
+
}
|
|
191
|
+
let builtInType: DataType;
|
|
192
|
+
let builtInUADataType: UADataType;
|
|
193
193
|
|
|
194
|
-
|
|
195
|
-
|
|
194
|
+
const destUADataType = addressSpace.findDataType(dataTypeNodeId)!;
|
|
195
|
+
assert(destUADataType instanceof UADataTypeImpl);
|
|
196
196
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
197
|
+
if (destUADataType.isAbstract || destUADataType.nodeId.namespace !== 0) {
|
|
198
|
+
builtInUADataType = destUADataType;
|
|
199
|
+
} else {
|
|
200
|
+
builtInType = addressSpace.findCorrespondingBasicDataType(destUADataType);
|
|
201
|
+
builtInUADataType = addressSpace.findDataType(builtInType)!;
|
|
202
|
+
}
|
|
203
|
+
assert(builtInUADataType instanceof UADataTypeImpl);
|
|
204
204
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
}
|
|
219
|
-
return true;
|
|
205
|
+
const enumerationUADataType = addressSpace.findDataType("Enumeration");
|
|
206
|
+
if (!enumerationUADataType) {
|
|
207
|
+
throw new Error("cannot find Enumeration DataType node in standard address space");
|
|
208
|
+
}
|
|
209
|
+
if (destUADataType.isSubtypeOf(enumerationUADataType)) {
|
|
210
|
+
// istanbul ignore next
|
|
211
|
+
if (doDebug) {
|
|
212
|
+
debugLog("destUADataType.", destUADataType.browseName.toString(), destUADataType.nodeId.toString());
|
|
213
|
+
debugLog(
|
|
214
|
+
"enumerationUADataType.",
|
|
215
|
+
enumerationUADataType.browseName.toString(),
|
|
216
|
+
enumerationUADataType.nodeId.toString()
|
|
217
|
+
);
|
|
220
218
|
}
|
|
219
|
+
return true;
|
|
220
|
+
}
|
|
221
221
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
222
|
+
// The value supplied for the attribute is not of the same type as the value.
|
|
223
|
+
const variantUADataType = _dataType_toUADataType(addressSpace, variantDataType);
|
|
224
|
+
assert(variantUADataType instanceof UADataTypeImpl);
|
|
225
225
|
|
|
226
|
-
|
|
226
|
+
const dest_isSubTypeOf_variant = variantUADataType.isSubtypeOf(builtInUADataType);
|
|
227
227
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
}
|
|
237
|
-
debugLog(chalk.cyan(" Variable data Type is = "), destUADataType.browseName.toString());
|
|
238
|
-
debugLog(chalk.cyan(" which matches basic Type = "), builtInUADataType.browseName.toString());
|
|
239
|
-
debugLog(chalk.yellow(" Actual dataType = "), variantUADataType.browseName.toString());
|
|
228
|
+
/* istanbul ignore next */
|
|
229
|
+
if (doDebug) {
|
|
230
|
+
if (dest_isSubTypeOf_variant) {
|
|
231
|
+
/* istanbul ignore next*/
|
|
232
|
+
debugLog(chalk.green(" ---------- Type match !!! "), " on ", nodeId.toString());
|
|
233
|
+
} else {
|
|
234
|
+
/* istanbul ignore next*/
|
|
235
|
+
debugLog(chalk.red(" ---------- Type mismatch "), " on ", nodeId.toString());
|
|
240
236
|
}
|
|
241
|
-
|
|
242
|
-
|
|
237
|
+
debugLog(chalk.cyan(" Variable data Type is = "), destUADataType.browseName.toString());
|
|
238
|
+
debugLog(chalk.cyan(" which matches basic Type = "), builtInUADataType.browseName.toString());
|
|
239
|
+
debugLog(chalk.yellow(" Actual dataType = "), variantUADataType.browseName.toString());
|
|
243
240
|
}
|
|
244
241
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
}
|
|
242
|
+
return dest_isSubTypeOf_variant;
|
|
243
|
+
}
|
|
248
244
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
/**
|
|
253
|
-
* This attribute indicates whether the Value attribute of the Variableis an array and how many dimensions the array has.
|
|
254
|
-
* It may have the following values:
|
|
255
|
-
* * n > 1: the Value is an array with the specified number of dimensions.
|
|
256
|
-
* * OneDimension (1): The value is an array with one dimension.
|
|
257
|
-
* * OneOrMoreDimensions (0): The value is an array with one or more dimensions.
|
|
258
|
-
* * Scalar (−1): The value is not an array.
|
|
259
|
-
* * Any (−2): The value can be a scalar or an array with any number of dimensions.
|
|
260
|
-
* * ScalarOrOneDimension (−3): The value can be a scalar or a one dimensional array.
|
|
261
|
-
* * All DataTypes are considered to be scalar, even if they have array-like semantics like ByteString and String.
|
|
262
|
-
*/
|
|
263
|
-
valueRank?: number;
|
|
264
|
-
arrayDimensions?: null | number[];
|
|
265
|
-
accessLevel?: any;
|
|
266
|
-
userAccessLevel?: any;
|
|
267
|
-
minimumSamplingInterval?: number; // default -1
|
|
268
|
-
historizing?: number;
|
|
269
|
-
}
|
|
245
|
+
function default_func(this: UAVariable, dataValue1: DataValue, callback1: CallbackT<StatusCode>) {
|
|
246
|
+
return _default_writable_timestamped_set_func.call(this, dataValue1, callback1);
|
|
247
|
+
}
|
|
270
248
|
|
|
249
|
+
interface UAVariableOptions extends InternalBaseNodeOptions {
|
|
250
|
+
value?: any;
|
|
251
|
+
dataType: NodeId | string;
|
|
271
252
|
/**
|
|
272
|
-
*
|
|
273
|
-
*
|
|
274
|
-
*
|
|
275
|
-
*
|
|
276
|
-
*
|
|
277
|
-
*
|
|
278
|
-
*
|
|
279
|
-
*
|
|
280
|
-
*
|
|
281
|
-
*
|
|
282
|
-
* Field Bit Description
|
|
283
|
-
* CurrentRead 0 Indicates if the current value is readable
|
|
284
|
-
* (0 means not readable, 1 means readable).
|
|
285
|
-
* CurrentWrite 1 Indicates if the current value is writable
|
|
286
|
-
* (0 means not writable, 1 means writable).
|
|
287
|
-
* HistoryRead 2 Indicates if the history of the value is readable
|
|
288
|
-
* (0 means not readable, 1 means readable).
|
|
289
|
-
* HistoryWrite 3 Indicates if the history of the value is writable (0 means not writable, 1 means writable).
|
|
290
|
-
* SemanticChange 4 Indicates if the Variable used as Property generates SemanticChangeEvents (see 9.31).
|
|
291
|
-
* Reserved 5:7 Reserved for future use. Shall always be zero.
|
|
292
|
-
*
|
|
293
|
-
* The first two bits also indicate if a current value of this Variable is available and the second two bits
|
|
294
|
-
* indicates if the history of the Variable is available via the OPC UA server.
|
|
295
|
-
*
|
|
253
|
+
* This attribute indicates whether the Value attribute of the Variableis an array and how many dimensions the array has.
|
|
254
|
+
* It may have the following values:
|
|
255
|
+
* * n > 1: the Value is an array with the specified number of dimensions.
|
|
256
|
+
* * OneDimension (1): The value is an array with one dimension.
|
|
257
|
+
* * OneOrMoreDimensions (0): The value is an array with one or more dimensions.
|
|
258
|
+
* * Scalar (−1): The value is not an array.
|
|
259
|
+
* * Any (−2): The value can be a scalar or an array with any number of dimensions.
|
|
260
|
+
* * ScalarOrOneDimension (−3): The value can be a scalar or a one dimensional array.
|
|
261
|
+
* * All DataTypes are considered to be scalar, even if they have array-like semantics like ByteString and String.
|
|
296
262
|
*/
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
263
|
+
valueRank?: number;
|
|
264
|
+
arrayDimensions?: null | number[];
|
|
265
|
+
accessLevel?: any;
|
|
266
|
+
userAccessLevel?: any;
|
|
267
|
+
minimumSamplingInterval?: number; // default -1
|
|
268
|
+
historizing?: number;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* A OPCUA Variable Node
|
|
273
|
+
*
|
|
274
|
+
* @class UAVariable
|
|
275
|
+
* @constructor
|
|
276
|
+
* @extends BaseNode
|
|
277
|
+
* The AccessLevel Attribute is used to indicate how the Value of a Variable can be accessed (read/write) and if it
|
|
278
|
+
* contains current and/or historic data. The AccessLevel does not take any user access rights into account,
|
|
279
|
+
* i.e. although the Variable is writable this may be restricted to a certain user / user group.
|
|
280
|
+
* The AccessLevel is an 8-bit unsigned integer with the structure defined in the following table:
|
|
281
|
+
*
|
|
282
|
+
* Field Bit Description
|
|
283
|
+
* CurrentRead 0 Indicates if the current value is readable
|
|
284
|
+
* (0 means not readable, 1 means readable).
|
|
285
|
+
* CurrentWrite 1 Indicates if the current value is writable
|
|
286
|
+
* (0 means not writable, 1 means writable).
|
|
287
|
+
* HistoryRead 2 Indicates if the history of the value is readable
|
|
288
|
+
* (0 means not readable, 1 means readable).
|
|
289
|
+
* HistoryWrite 3 Indicates if the history of the value is writable (0 means not writable, 1 means writable).
|
|
290
|
+
* SemanticChange 4 Indicates if the Variable used as Property generates SemanticChangeEvents (see 9.31).
|
|
291
|
+
* Reserved 5:7 Reserved for future use. Shall always be zero.
|
|
292
|
+
*
|
|
293
|
+
* The first two bits also indicate if a current value of this Variable is available and the second two bits
|
|
294
|
+
* indicates if the history of the Variable is available via the OPC UA server.
|
|
295
|
+
*
|
|
296
|
+
*/
|
|
297
|
+
export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
298
|
+
public readonly nodeClass = NodeClass.Variable;
|
|
299
|
+
|
|
300
|
+
public dataType: NodeId;
|
|
301
|
+
private _basicDataType?: DataType;
|
|
302
|
+
|
|
303
|
+
public $extensionObject?: any;
|
|
304
|
+
public $set_ExtensionObject?: (newValue: ExtensionObject, sourceTimestamp: PreciseClock, cache: Set<UAVariableImpl>) => void;
|
|
305
|
+
|
|
306
|
+
public $historicalDataConfiguration?: UAHistoricalDataConfiguration;
|
|
307
|
+
public varHistorian?: IVariableHistorian;
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* @internal @private
|
|
311
|
+
*/
|
|
312
|
+
public $dataValue: DataValue;
|
|
313
|
+
public accessLevel: number;
|
|
314
|
+
public userAccessLevel?: number;
|
|
315
|
+
public valueRank: number;
|
|
316
|
+
public minimumSamplingInterval: number;
|
|
317
|
+
public historizing: boolean;
|
|
318
|
+
public semantic_version: number;
|
|
319
|
+
public arrayDimensions: null | number[];
|
|
320
|
+
|
|
321
|
+
public _timestamped_get_func?: TimestampGetFunc | null;
|
|
322
|
+
public _timestamped_set_func?: VariableDataValueSetterWithCallback | null;
|
|
323
|
+
public _get_func: any;
|
|
324
|
+
public _set_func: any;
|
|
325
|
+
public refreshFunc?: (callback: CallbackT<DataValue>) => void;
|
|
326
|
+
public __waiting_callbacks?: any[];
|
|
327
|
+
|
|
328
|
+
get typeDefinitionObj(): UAVariableType {
|
|
329
|
+
// istanbul ignore next
|
|
330
|
+
if (super.typeDefinitionObj && super.typeDefinitionObj.nodeClass !== NodeClass.VariableType) {
|
|
331
|
+
console.log(super.typeDefinitionObj.toString());
|
|
332
|
+
throw new Error(
|
|
333
|
+
"Invalid type definition node class , expecting a VariableType got " + NodeClass[super.typeDefinitionObj.nodeClass]
|
|
334
|
+
);
|
|
340
335
|
}
|
|
341
|
-
|
|
342
|
-
|
|
336
|
+
return super.typeDefinitionObj as UAVariableType;
|
|
337
|
+
}
|
|
338
|
+
get typeDefinition(): NodeId {
|
|
339
|
+
return super.typeDefinition;
|
|
340
|
+
}
|
|
341
|
+
constructor(options: UAVariableOptions) {
|
|
342
|
+
super(options);
|
|
343
343
|
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
344
|
+
verifyRankAndDimensions(options);
|
|
345
|
+
this.valueRank = options.valueRank!;
|
|
346
|
+
this.arrayDimensions = options.arrayDimensions!;
|
|
347
347
|
|
|
348
|
-
|
|
348
|
+
this.dataType = this.resolveNodeId(options.dataType); // DataType (NodeId)
|
|
349
349
|
|
|
350
|
-
|
|
350
|
+
this.accessLevel = adjust_accessLevel(options.accessLevel);
|
|
351
351
|
|
|
352
|
-
|
|
352
|
+
this.userAccessLevel = adjust_userAccessLevel(options.userAccessLevel, this.accessLevel);
|
|
353
353
|
|
|
354
|
-
|
|
354
|
+
this.minimumSamplingInterval = adjust_samplingInterval(options.minimumSamplingInterval || 0);
|
|
355
355
|
|
|
356
|
-
|
|
356
|
+
this.historizing = !!options.historizing; // coerced to boolean"
|
|
357
357
|
|
|
358
|
-
|
|
358
|
+
this.$dataValue = new DataValue({ statusCode: StatusCodes.UncertainInitialValue, value: { dataType: DataType.Null } });
|
|
359
359
|
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
360
|
+
if (options.value) {
|
|
361
|
+
this.bindVariable(options.value);
|
|
362
|
+
}
|
|
363
363
|
|
|
364
|
-
|
|
364
|
+
this.setMaxListeners(5000);
|
|
365
365
|
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
return true;
|
|
373
|
-
}
|
|
374
|
-
return (this.userAccessLevel & accessLevel) === accessLevel;
|
|
375
|
-
}
|
|
376
|
-
private checkPermissionPrivate(
|
|
377
|
-
context: ISessionContext,
|
|
378
|
-
permission: PermissionType,
|
|
379
|
-
): boolean {
|
|
380
|
-
if (!context) return true;
|
|
381
|
-
assert(context instanceof SessionContext);
|
|
382
|
-
if (context.checkPermission) {
|
|
383
|
-
if (!(context.checkPermission instanceof Function)) {
|
|
384
|
-
errorLog("context checkPermission is not a function");
|
|
385
|
-
return false;
|
|
386
|
-
}
|
|
387
|
-
if (!context.checkPermission(this, permission)) {
|
|
388
|
-
return false;
|
|
389
|
-
}
|
|
390
|
-
}
|
|
366
|
+
this.semantic_version = 0;
|
|
367
|
+
}
|
|
368
|
+
private checkAccessLevelPrivate(
|
|
369
|
+
_context: ISessionContext,
|
|
370
|
+
accessLevel: AccessLevelFlag): boolean {
|
|
371
|
+
if (this.userAccessLevel === undefined) {
|
|
391
372
|
return true;
|
|
392
373
|
}
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
return (this.accessLevel & AccessLevelFlag.CurrentRead) === AccessLevelFlag.CurrentRead;
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
public isUserReadable(context: ISessionContext): boolean {
|
|
408
|
-
if (!this.isReadable(context)) {
|
|
374
|
+
return (this.userAccessLevel & accessLevel) === accessLevel;
|
|
375
|
+
}
|
|
376
|
+
private checkPermissionPrivate(
|
|
377
|
+
context: ISessionContext,
|
|
378
|
+
permission: PermissionType,
|
|
379
|
+
): boolean {
|
|
380
|
+
if (!context) return true;
|
|
381
|
+
assert(context instanceof SessionContext);
|
|
382
|
+
if (context.checkPermission) {
|
|
383
|
+
if (!(context.checkPermission instanceof Function)) {
|
|
384
|
+
errorLog("context checkPermission is not a function");
|
|
409
385
|
return false;
|
|
410
386
|
}
|
|
411
|
-
if (!
|
|
387
|
+
if (!context.checkPermission(this, permission)) {
|
|
412
388
|
return false;
|
|
413
389
|
}
|
|
414
|
-
return this.checkAccessLevelPrivate(context, AccessLevelFlag.CurrentRead);
|
|
415
390
|
}
|
|
391
|
+
return true;
|
|
392
|
+
}
|
|
393
|
+
private checkPermissionAndAccessLevelPrivate(
|
|
394
|
+
context: ISessionContext,
|
|
395
|
+
permission: PermissionType,
|
|
396
|
+
accessLevel: AccessLevelFlag): boolean {
|
|
397
|
+
if (!this.checkPermissionPrivate(context, permission)) {
|
|
398
|
+
return false;
|
|
399
|
+
}
|
|
400
|
+
return this.checkAccessLevelPrivate(context, accessLevel);
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
public isReadable(context: ISessionContext): boolean {
|
|
404
|
+
return (this.accessLevel & AccessLevelFlag.CurrentRead) === AccessLevelFlag.CurrentRead;
|
|
405
|
+
}
|
|
416
406
|
|
|
417
|
-
|
|
418
|
-
|
|
407
|
+
public isUserReadable(context: ISessionContext): boolean {
|
|
408
|
+
if (!this.isReadable(context)) {
|
|
409
|
+
return false;
|
|
410
|
+
}
|
|
411
|
+
if (!this.checkPermissionPrivate(context, PermissionType.Read)) {
|
|
412
|
+
return false;
|
|
419
413
|
}
|
|
414
|
+
return this.checkAccessLevelPrivate(context, AccessLevelFlag.CurrentRead);
|
|
415
|
+
}
|
|
420
416
|
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
417
|
+
public isWritable(context: ISessionContext): boolean {
|
|
418
|
+
return (this.accessLevel & AccessLevelFlag.CurrentWrite) === AccessLevelFlag.CurrentWrite;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
public isUserWritable(context: ISessionContext): boolean {
|
|
422
|
+
if (!this.isWritable(context)) {
|
|
423
|
+
return false;
|
|
426
424
|
}
|
|
425
|
+
return this.checkPermissionAndAccessLevelPrivate(context, PermissionType.Write, AccessLevelFlag.CurrentWrite);
|
|
426
|
+
}
|
|
427
427
|
|
|
428
|
-
|
|
429
|
-
|
|
428
|
+
public canUserReadHistory(context: ISessionContext): boolean {
|
|
429
|
+
return this.checkPermissionAndAccessLevelPrivate(context, PermissionType.ReadHistory, AccessLevelFlag.HistoryRead);
|
|
430
|
+
}
|
|
431
|
+
public canUserWriteHistorizingAttribute(context: ISessionContext): boolean {
|
|
432
|
+
if (context && !context.checkPermission(this, PermissionType.WriteHistorizing)) {
|
|
433
|
+
return false;
|
|
430
434
|
}
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
435
|
+
return true;
|
|
436
|
+
}
|
|
437
|
+
public canUserInsertHistory(context: ISessionContext): boolean {
|
|
438
|
+
return this.checkPermissionAndAccessLevelPrivate(context, PermissionType.InsertHistory, AccessLevelFlag.HistoryWrite);
|
|
439
|
+
}
|
|
440
|
+
public canUserModifyHistory(context: ISessionContext): boolean {
|
|
441
|
+
return this.checkPermissionAndAccessLevelPrivate(context, PermissionType.ModifyHistory, AccessLevelFlag.HistoryWrite);
|
|
442
|
+
}
|
|
443
|
+
public canUserDeleteHistory(context: ISessionContext): boolean {
|
|
444
|
+
return this.checkPermissionAndAccessLevelPrivate(context, PermissionType.DeleteHistory, AccessLevelFlag.HistoryWrite);
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
/**
|
|
448
|
+
*
|
|
449
|
+
*
|
|
450
|
+
* from OPC.UA.Spec 1.02 part 4
|
|
451
|
+
* 5.10.2.4 StatusCodes
|
|
452
|
+
* Table 51 defines values for the operation level statusCode contained in the DataValue structure of
|
|
453
|
+
* each values element. Common StatusCodes are defined in Table 166.
|
|
454
|
+
*
|
|
455
|
+
* Table 51 Read Operation Level Result Codes
|
|
456
|
+
*
|
|
457
|
+
* | Symbolic Id | Description
|
|
458
|
+
* |-----------------------------|---------------------------------------------------------------------------------------------|
|
|
459
|
+
* |BadNodeIdInvalid | The syntax of the node id is not valid.|
|
|
460
|
+
* |BadNodeIdUnknown |The node id refers to a node that does not exist in the server address space.|
|
|
461
|
+
* |BadAttributeIdInvalid | BadAttributeIdInvalid The attribute is not supported for the specified node.|
|
|
462
|
+
* |BadIndexRangeInvalid | The syntax of the index range parameter is invalid.|
|
|
463
|
+
* |BadIndexRangeNoData | No data exists within the range of indexes specified.|
|
|
464
|
+
* |BadDataEncodingInvalid | The data encoding is invalid.|
|
|
465
|
+
* | | This result is used if no dataEncoding can be applied because an Attribute other|
|
|
466
|
+
* | | than Value was requested or the DataType of the Value Attribute is not a subtype|
|
|
467
|
+
* | | of the Structure DataType.|
|
|
468
|
+
* |BadDataEncodingUnsupported | The server does not support the requested data encoding for the node. |
|
|
469
|
+
* | | This result is used if a dataEncoding can be applied but the passed data encoding |
|
|
470
|
+
* | | is not known to the Server. |
|
|
471
|
+
* |BadNotReadable | The access level does not allow reading or subscribing to the Node.|
|
|
472
|
+
* |BadUserAccessDenied | User does not have permission to perform the requested operation. (table 165)|
|
|
473
|
+
*/
|
|
474
|
+
public readValue(
|
|
475
|
+
context?: ISessionContext | null,
|
|
476
|
+
indexRange?: NumericRange,
|
|
477
|
+
dataEncoding?: QualifiedNameLike | null
|
|
478
|
+
): DataValue {
|
|
479
|
+
if (!context) {
|
|
480
|
+
context = SessionContext.defaultContext;
|
|
436
481
|
}
|
|
437
|
-
public canUserInsertHistory(context: ISessionContext): boolean {
|
|
438
|
-
return this.checkPermissionAndAccessLevelPrivate(context, PermissionType.InsertHistory, AccessLevelFlag.HistoryWrite);
|
|
439
|
-
}
|
|
440
|
-
public canUserModifyHistory(context: ISessionContext): boolean {
|
|
441
|
-
return this.checkPermissionAndAccessLevelPrivate(context, PermissionType.ModifyHistory, AccessLevelFlag.HistoryWrite);
|
|
442
|
-
}
|
|
443
|
-
public canUserDeleteHistory(context: ISessionContext): boolean {
|
|
444
|
-
return this.checkPermissionAndAccessLevelPrivate(context, PermissionType.DeleteHistory, AccessLevelFlag.HistoryWrite);
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
/**
|
|
448
|
-
*
|
|
449
|
-
*
|
|
450
|
-
* from OPC.UA.Spec 1.02 part 4
|
|
451
|
-
* 5.10.2.4 StatusCodes
|
|
452
|
-
* Table 51 defines values for the operation level statusCode contained in the DataValue structure of
|
|
453
|
-
* each values element. Common StatusCodes are defined in Table 166.
|
|
454
|
-
*
|
|
455
|
-
* Table 51 Read Operation Level Result Codes
|
|
456
|
-
*
|
|
457
|
-
* | Symbolic Id | Description
|
|
458
|
-
* |-----------------------------|---------------------------------------------------------------------------------------------|
|
|
459
|
-
* |BadNodeIdInvalid | The syntax of the node id is not valid.|
|
|
460
|
-
* |BadNodeIdUnknown |The node id refers to a node that does not exist in the server address space.|
|
|
461
|
-
* |BadAttributeIdInvalid | BadAttributeIdInvalid The attribute is not supported for the specified node.|
|
|
462
|
-
* |BadIndexRangeInvalid | The syntax of the index range parameter is invalid.|
|
|
463
|
-
* |BadIndexRangeNoData | No data exists within the range of indexes specified.|
|
|
464
|
-
* |BadDataEncodingInvalid | The data encoding is invalid.|
|
|
465
|
-
* | | This result is used if no dataEncoding can be applied because an Attribute other|
|
|
466
|
-
* | | than Value was requested or the DataType of the Value Attribute is not a subtype|
|
|
467
|
-
* | | of the Structure DataType.|
|
|
468
|
-
* |BadDataEncodingUnsupported | The server does not support the requested data encoding for the node. |
|
|
469
|
-
* | | This result is used if a dataEncoding can be applied but the passed data encoding |
|
|
470
|
-
* | | is not known to the Server. |
|
|
471
|
-
* |BadNotReadable | The access level does not allow reading or subscribing to the Node.|
|
|
472
|
-
* |BadUserAccessDenied | User does not have permission to perform the requested operation. (table 165)|
|
|
473
|
-
*/
|
|
474
|
-
public readValue(
|
|
475
|
-
context?: ISessionContext | null,
|
|
476
|
-
indexRange?: NumericRange,
|
|
477
|
-
dataEncoding?: QualifiedNameLike | null
|
|
478
|
-
): DataValue {
|
|
479
|
-
if (!context) {
|
|
480
|
-
context = SessionContext.defaultContext;
|
|
481
|
-
}
|
|
482
482
|
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
483
|
+
if (context.isAccessRestricted(this)) {
|
|
484
|
+
return new DataValue({ statusCode: StatusCodes.BadSecurityModeInsufficient });
|
|
485
|
+
}
|
|
486
486
|
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
487
|
+
if (!this.isReadable(context)) {
|
|
488
|
+
return new DataValue({ statusCode: StatusCodes.BadNotReadable });
|
|
489
|
+
}
|
|
490
|
+
if (!this.checkPermissionPrivate(context, PermissionType.Read)) {
|
|
491
|
+
return new DataValue({ statusCode: StatusCodes.BadUserAccessDenied });
|
|
492
|
+
}
|
|
493
|
+
if (!this.isUserReadable(context)) {
|
|
494
|
+
return new DataValue({ statusCode: StatusCodes.BadNotReadable });
|
|
495
|
+
}
|
|
496
|
+
if (!isValidDataEncoding(dataEncoding)) {
|
|
497
|
+
return new DataValue({ statusCode: StatusCodes.BadDataEncodingInvalid });
|
|
498
|
+
}
|
|
499
499
|
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
}
|
|
509
|
-
} else {
|
|
510
|
-
errorLog("Unsupported: _timestamped_get_func returns a Promise !");
|
|
500
|
+
if (this._timestamped_get_func) {
|
|
501
|
+
if (this._timestamped_get_func.length === 0) {
|
|
502
|
+
const dataValueOrPromise = (this._timestamped_get_func as VariableDataValueGetterSync)();
|
|
503
|
+
if (!Object.prototype.hasOwnProperty.call(dataValueOrPromise, "then")) {
|
|
504
|
+
if (dataValueOrPromise !== this.$dataValue) {
|
|
505
|
+
// TO DO : is this necessary ? this may interfere with current use of $dataValue
|
|
506
|
+
this.$dataValue = dataValueOrPromise as DataValue;
|
|
507
|
+
this.verifyVariantCompatibility(this.$dataValue.value);
|
|
511
508
|
}
|
|
509
|
+
} else {
|
|
510
|
+
errorLog("Unsupported: _timestamped_get_func returns a Promise !");
|
|
512
511
|
}
|
|
513
512
|
}
|
|
513
|
+
}
|
|
514
514
|
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
if (dataValue.statusCode.isGoodish()) {
|
|
518
|
-
// note : extractRange will clone the dataValue
|
|
519
|
-
dataValue = extractRange(dataValue, indexRange);
|
|
520
|
-
}
|
|
515
|
+
let dataValue = this.$dataValue;
|
|
521
516
|
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
dataValue.statusCode.equals(StatusCodes.UncertainInitialValue)
|
|
526
|
-
) {
|
|
527
|
-
debugLog(
|
|
528
|
-
chalk.red(" Warning: UAVariable#readValue ") +
|
|
529
|
-
chalk.cyan(this.browseName.toString()) +
|
|
530
|
-
" (" +
|
|
531
|
-
chalk.yellow(this.nodeId.toString()) +
|
|
532
|
-
") exists but dataValue has not been defined"
|
|
533
|
-
);
|
|
534
|
-
}
|
|
535
|
-
return dataValue;
|
|
517
|
+
if (dataValue.statusCode.isGoodish()) {
|
|
518
|
+
// note : extractRange will clone the dataValue
|
|
519
|
+
dataValue = extractRange(dataValue, indexRange);
|
|
536
520
|
}
|
|
537
521
|
|
|
538
|
-
|
|
539
|
-
|
|
522
|
+
/* istanbul ignore next */
|
|
523
|
+
if (
|
|
524
|
+
dataValue.statusCode.equals(StatusCodes.BadWaitingForInitialData) ||
|
|
525
|
+
dataValue.statusCode.equals(StatusCodes.UncertainInitialValue)
|
|
526
|
+
) {
|
|
527
|
+
debugLog(
|
|
528
|
+
chalk.red(" Warning: UAVariable#readValue ") +
|
|
529
|
+
chalk.cyan(this.browseName.toString()) +
|
|
530
|
+
" (" +
|
|
531
|
+
chalk.yellow(this.nodeId.toString()) +
|
|
532
|
+
") exists but dataValue has not been defined"
|
|
533
|
+
);
|
|
540
534
|
}
|
|
535
|
+
return dataValue;
|
|
536
|
+
}
|
|
541
537
|
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
*/
|
|
546
|
-
public isExtensionObject(): boolean {
|
|
547
|
-
// DataType must be one of Structure
|
|
548
|
-
if (this.dataType.isEmpty()) return false;
|
|
549
|
-
const dataTypeNode = this.addressSpace.findDataType(this.dataType) as UADataType;
|
|
550
|
-
if (!dataTypeNode) {
|
|
551
|
-
throw new Error(" Cannot find DataType " + this.dataType.toString() + " in standard address Space");
|
|
552
|
-
}
|
|
553
|
-
const structureNode = this.addressSpace.findDataType("Structure")!;
|
|
554
|
-
if (!structureNode) {
|
|
555
|
-
throw new Error(" Cannot find 'Structure' DataType in standard address Space");
|
|
556
|
-
}
|
|
557
|
-
return dataTypeNode.isSubtypeOf(structureNode);
|
|
558
|
-
}
|
|
538
|
+
public isEnumeration(): boolean {
|
|
539
|
+
return this.addressSpacePrivate.isEnumeration(this.dataType);
|
|
540
|
+
}
|
|
559
541
|
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
542
|
+
/**
|
|
543
|
+
* return true if the DataType is of type Extension object
|
|
544
|
+
* this is not taking into account the valueRank of the variable
|
|
545
|
+
*/
|
|
546
|
+
public isExtensionObject(): boolean {
|
|
547
|
+
// DataType must be one of Structure
|
|
548
|
+
if (this.dataType.isEmpty()) return false;
|
|
549
|
+
const dataTypeNode = this.addressSpace.findDataType(this.dataType) as UADataType;
|
|
550
|
+
if (!dataTypeNode) {
|
|
551
|
+
throw new Error(" Cannot find DataType " + this.dataType.toString() + " in standard address Space");
|
|
565
552
|
}
|
|
553
|
+
const structureNode = this.addressSpace.findDataType("Structure")!;
|
|
554
|
+
if (!structureNode) {
|
|
555
|
+
throw new Error(" Cannot find 'Structure' DataType in standard address Space");
|
|
556
|
+
}
|
|
557
|
+
return dataTypeNode.isSubtypeOf(structureNode);
|
|
558
|
+
}
|
|
566
559
|
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
560
|
+
public _getEnumerationInfo(): EnumerationInfo {
|
|
561
|
+
// DataType must be one of Enumeration
|
|
562
|
+
assert(this.isEnumeration(), "Variable is not an enumeration");
|
|
563
|
+
const dataTypeNode = this.addressSpace.findDataType(this.dataType)! as UADataTypeImpl;
|
|
564
|
+
return dataTypeNode._getEnumerationInfo();
|
|
565
|
+
}
|
|
573
566
|
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
const dataValue = this.readValue();
|
|
581
|
-
dataValue.serverTimestamp = oldestDate;
|
|
582
|
-
dataValue.serverPicoseconds = 0;
|
|
583
|
-
if (oldestDate.getTime() <= dataValue.serverTimestamp!.getTime()) {
|
|
584
|
-
return callback(null, dataValue);
|
|
585
|
-
} else {
|
|
586
|
-
// fake
|
|
587
|
-
return callback(null, dataValue);
|
|
588
|
-
}
|
|
589
|
-
}
|
|
567
|
+
public asyncRefresh(oldestDate: Date, callback: CallbackT<DataValue>): void;
|
|
568
|
+
public asyncRefresh(oldestDate: Date): Promise<DataValue>;
|
|
569
|
+
public asyncRefresh(...args: any[]): any {
|
|
570
|
+
if (this.$dataValue.statusCode.isGoodish()) {
|
|
571
|
+
this.verifyVariantCompatibility(this.$dataValue.value);
|
|
572
|
+
}
|
|
590
573
|
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
574
|
+
const oldestDate = args[0] as Date;
|
|
575
|
+
assert(oldestDate instanceof Date);
|
|
576
|
+
const callback = args[1] as CallbackT<DataValue>;
|
|
577
|
+
|
|
578
|
+
if (!this.refreshFunc) {
|
|
579
|
+
// no refresh func
|
|
580
|
+
const dataValue = this.readValue();
|
|
581
|
+
dataValue.serverTimestamp = oldestDate;
|
|
582
|
+
dataValue.serverPicoseconds = 0;
|
|
583
|
+
if (oldestDate.getTime() <= dataValue.serverTimestamp!.getTime()) {
|
|
584
|
+
return callback(null, dataValue);
|
|
585
|
+
} else {
|
|
586
|
+
// fake
|
|
595
587
|
return callback(null, dataValue);
|
|
596
|
-
}
|
|
597
|
-
try {
|
|
598
|
-
this.refreshFunc.call(this, (err: Error | null, dataValue?: DataValueLike) => {
|
|
599
|
-
// istanbul ignore next
|
|
600
|
-
if (err || !dataValue) {
|
|
601
|
-
errorLog(
|
|
602
|
-
"-------------- refresh call failed",
|
|
603
|
-
this.browseName.toString(),
|
|
604
|
-
this.nodeId.toString(),
|
|
605
|
-
err?.message
|
|
606
|
-
);
|
|
607
|
-
dataValue = { statusCode: StatusCodes.BadNoDataAvailable };
|
|
608
|
-
}
|
|
609
|
-
if (dataValue && dataValue !== this.$dataValue) {
|
|
610
|
-
this._internal_set_dataValue(coerceDataValue(dataValue), null);
|
|
611
|
-
}
|
|
612
|
-
callback(err, this.$dataValue);
|
|
613
|
-
});
|
|
614
|
-
} catch (err) {
|
|
615
|
-
errorLog("-------------- refresh call failed 2", this.browseName.toString(), this.nodeId.toString());
|
|
616
|
-
errorLog(err);
|
|
617
|
-
const dataValue = new DataValue({ statusCode: StatusCodes.BadInternalError });
|
|
618
|
-
this._internal_set_dataValue(dataValue, null);
|
|
619
|
-
callback(err as Error, this.$dataValue);
|
|
620
588
|
}
|
|
621
589
|
}
|
|
622
590
|
|
|
623
|
-
|
|
624
|
-
const
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
return
|
|
591
|
+
if (this.$dataValue.serverTimestamp && oldestDate.getTime() <= this.$dataValue.serverTimestamp!.getTime()) {
|
|
592
|
+
const dataValue = this.readValue().clone();
|
|
593
|
+
dataValue.serverTimestamp = oldestDate;
|
|
594
|
+
dataValue.serverPicoseconds = 0;
|
|
595
|
+
return callback(null, dataValue);
|
|
596
|
+
}
|
|
597
|
+
try {
|
|
598
|
+
this.refreshFunc.call(this, (err: Error | null, dataValue?: DataValueLike) => {
|
|
599
|
+
// istanbul ignore next
|
|
600
|
+
if (err || !dataValue) {
|
|
601
|
+
errorLog(
|
|
602
|
+
"-------------- refresh call failed",
|
|
603
|
+
this.browseName.toString(),
|
|
604
|
+
this.nodeId.toString(),
|
|
605
|
+
err?.message
|
|
606
|
+
);
|
|
607
|
+
dataValue = { statusCode: StatusCodes.BadNoDataAvailable };
|
|
608
|
+
}
|
|
609
|
+
if (dataValue && dataValue !== this.$dataValue) {
|
|
610
|
+
this._internal_set_dataValue(coerceDataValue(dataValue), null);
|
|
611
|
+
}
|
|
612
|
+
callback(err, this.$dataValue);
|
|
613
|
+
});
|
|
614
|
+
} catch (err) {
|
|
615
|
+
errorLog("-------------- refresh call failed 2", this.browseName.toString(), this.nodeId.toString());
|
|
616
|
+
errorLog(err);
|
|
617
|
+
const dataValue = new DataValue({ statusCode: StatusCodes.BadInternalError });
|
|
618
|
+
this._internal_set_dataValue(dataValue, null);
|
|
619
|
+
callback(err as Error, this.$dataValue);
|
|
628
620
|
}
|
|
621
|
+
}
|
|
629
622
|
|
|
630
|
-
|
|
631
|
-
|
|
623
|
+
public readEnumValue(): IEnumItem {
|
|
624
|
+
const value = this.readValue().value.value as number;
|
|
625
|
+
const enumInfo = this._getEnumerationInfo();
|
|
626
|
+
const enumV = enumInfo.valueIndex[value];
|
|
627
|
+
return { value, name: enumV ? enumV.name : "?????" };
|
|
628
|
+
}
|
|
632
629
|
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
const valueIndex = enumInfo.nameIndex[value].value;
|
|
639
|
-
value = valueIndex;
|
|
640
|
-
}
|
|
641
|
-
if (isFinite(value)) {
|
|
630
|
+
public writeEnumValue(value: string | number): void {
|
|
631
|
+
const enumInfo = this._getEnumerationInfo();
|
|
632
|
+
|
|
633
|
+
if (typeof value === "string") {
|
|
634
|
+
if (!Object.prototype.hasOwnProperty.call(enumInfo.nameIndex, value)) {
|
|
642
635
|
const possibleValues = Object.keys(enumInfo.nameIndex).join(",");
|
|
636
|
+
throw new Error("UAVariable#writeEnumValue: cannot find value " + value + " in [" + possibleValues + "]");
|
|
637
|
+
}
|
|
638
|
+
const valueIndex = enumInfo.nameIndex[value].value;
|
|
639
|
+
value = valueIndex;
|
|
640
|
+
}
|
|
641
|
+
if (isFinite(value)) {
|
|
642
|
+
const possibleValues = Object.keys(enumInfo.nameIndex).join(",");
|
|
643
643
|
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
}
|
|
647
|
-
this.setValueFromSource({
|
|
648
|
-
dataType: DataType.Int32,
|
|
649
|
-
value
|
|
650
|
-
});
|
|
651
|
-
} else {
|
|
652
|
-
throw new Error("UAVariable#writeEnumValue: value type mismatch");
|
|
644
|
+
if (!enumInfo.valueIndex[value]) {
|
|
645
|
+
throw new Error("UAVariable#writeEnumValue : value out of range " + value + " in [" + possibleValues + "]");
|
|
653
646
|
}
|
|
647
|
+
this.setValueFromSource({
|
|
648
|
+
dataType: DataType.Int32,
|
|
649
|
+
value
|
|
650
|
+
});
|
|
651
|
+
} else {
|
|
652
|
+
throw new Error("UAVariable#writeEnumValue: value type mismatch");
|
|
654
653
|
}
|
|
654
|
+
}
|
|
655
655
|
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
656
|
+
public readAttribute(
|
|
657
|
+
context: ISessionContext | null,
|
|
658
|
+
attributeId: AttributeIds,
|
|
659
|
+
indexRange?: NumericRange,
|
|
660
|
+
dataEncoding?: QualifiedNameLike | null
|
|
661
|
+
): DataValue {
|
|
662
|
+
context = context || SessionContext.defaultContext;
|
|
663
|
+
assert(context instanceof SessionContext);
|
|
664
664
|
|
|
665
|
-
|
|
665
|
+
const options: DataValueLike = {};
|
|
666
666
|
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
}
|
|
667
|
+
if (attributeId !== AttributeIds.Value) {
|
|
668
|
+
if (indexRange && indexRange.isDefined()) {
|
|
669
|
+
options.statusCode = StatusCodes.BadIndexRangeNoData;
|
|
670
|
+
return new DataValue(options);
|
|
671
|
+
}
|
|
672
|
+
if (isDataEncoding(dataEncoding)) {
|
|
673
|
+
options.statusCode = StatusCodes.BadDataEncodingInvalid;
|
|
674
|
+
return new DataValue(options);
|
|
676
675
|
}
|
|
676
|
+
}
|
|
677
677
|
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
678
|
+
switch (attributeId) {
|
|
679
|
+
case AttributeIds.Value:
|
|
680
|
+
return this.readValue(context, indexRange, dataEncoding);
|
|
681
681
|
|
|
682
|
-
|
|
683
|
-
|
|
682
|
+
case AttributeIds.DataType:
|
|
683
|
+
return this._readDataType();
|
|
684
684
|
|
|
685
|
-
|
|
686
|
-
|
|
685
|
+
case AttributeIds.ValueRank:
|
|
686
|
+
return this._readValueRank();
|
|
687
687
|
|
|
688
|
-
|
|
689
|
-
|
|
688
|
+
case AttributeIds.ArrayDimensions:
|
|
689
|
+
return this._readArrayDimensions();
|
|
690
690
|
|
|
691
|
-
|
|
692
|
-
|
|
691
|
+
case AttributeIds.AccessLevel:
|
|
692
|
+
return this._readAccessLevel(context);
|
|
693
693
|
|
|
694
|
-
|
|
695
|
-
|
|
694
|
+
case AttributeIds.UserAccessLevel:
|
|
695
|
+
return this._readUserAccessLevel(context);
|
|
696
696
|
|
|
697
|
-
|
|
698
|
-
|
|
697
|
+
case AttributeIds.MinimumSamplingInterval:
|
|
698
|
+
return this._readMinimumSamplingInterval();
|
|
699
699
|
|
|
700
|
-
|
|
701
|
-
|
|
700
|
+
case AttributeIds.Historizing:
|
|
701
|
+
return this._readHistorizing();
|
|
702
702
|
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
}
|
|
703
|
+
case AttributeIds.AccessLevelEx:
|
|
704
|
+
return this._readAccessLevelEx(context);
|
|
705
|
+
default:
|
|
706
|
+
return BaseNodeImpl.prototype.readAttribute.call(this, context, attributeId);
|
|
708
707
|
}
|
|
708
|
+
}
|
|
709
709
|
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
}
|
|
714
|
-
if (this.dataType.namespace === 0 && this.dataType.value === 0) {
|
|
715
|
-
return DataType.Null;
|
|
716
|
-
}
|
|
717
|
-
const addressSpace = this.addressSpace;
|
|
718
|
-
if (!addressSpace) {
|
|
719
|
-
// may be node has been deleted already
|
|
720
|
-
return DataType.Null;
|
|
721
|
-
}
|
|
722
|
-
const dataTypeNode = addressSpace.findDataType(this.dataType)!;
|
|
723
|
-
const basicDataType =
|
|
724
|
-
dataTypeNode && dataTypeNode.nodeClass === NodeClass.DataType ? dataTypeNode.getBasicDataType() : DataType.Null;
|
|
725
|
-
// const basicDataType = addressSpace.findCorrespondingBasicDataType(this.dataType);
|
|
726
|
-
this._basicDataType = basicDataType;
|
|
727
|
-
return basicDataType;
|
|
710
|
+
public getBasicDataType(): DataType {
|
|
711
|
+
if (this._basicDataType) {
|
|
712
|
+
return this._basicDataType;
|
|
728
713
|
}
|
|
729
|
-
|
|
730
|
-
return
|
|
714
|
+
if (this.dataType.namespace === 0 && this.dataType.value === 0) {
|
|
715
|
+
return DataType.Null;
|
|
731
716
|
}
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
this.dataType.
|
|
757
|
-
|
|
758
|
-
variant.dataType !== DataType.LocalizedText &&
|
|
759
|
-
variant.dataType !== DataType.Null
|
|
760
|
-
) {
|
|
761
|
-
throw new Error(
|
|
762
|
-
"Variant must provide a valid LocalizedText : variant = " +
|
|
763
|
-
variant.toString() +
|
|
764
|
-
" this.dataType= " +
|
|
765
|
-
this.dataType.toString()
|
|
766
|
-
);
|
|
767
|
-
}
|
|
768
|
-
}
|
|
769
|
-
const basicType = this.getBasicDataType();
|
|
770
|
-
|
|
771
|
-
if (basicType === DataType.String && variant.dataType === DataType.ByteString) {
|
|
772
|
-
return; // this is allowed
|
|
717
|
+
const addressSpace = this.addressSpace;
|
|
718
|
+
if (!addressSpace) {
|
|
719
|
+
// may be node has been deleted already
|
|
720
|
+
return DataType.Null;
|
|
721
|
+
}
|
|
722
|
+
const dataTypeNode = addressSpace.findDataType(this.dataType)!;
|
|
723
|
+
const basicDataType =
|
|
724
|
+
dataTypeNode && dataTypeNode.nodeClass === NodeClass.DataType ? dataTypeNode.getBasicDataType() : DataType.Null;
|
|
725
|
+
// const basicDataType = addressSpace.findCorrespondingBasicDataType(this.dataType);
|
|
726
|
+
this._basicDataType = basicDataType;
|
|
727
|
+
return basicDataType;
|
|
728
|
+
}
|
|
729
|
+
public adjustVariant(variant: Variant): Variant {
|
|
730
|
+
return adjustVariant(variant, this.valueRank, this.getBasicDataType());
|
|
731
|
+
}
|
|
732
|
+
public verifyVariantCompatibility(variant: Variant): void {
|
|
733
|
+
try {
|
|
734
|
+
// istanbul ignore next
|
|
735
|
+
if (Object.prototype.hasOwnProperty.call(variant, "value")) {
|
|
736
|
+
if (variant.dataType === null || variant.dataType === undefined) {
|
|
737
|
+
throw new Error(
|
|
738
|
+
"Variant must provide a valid dataType : variant = " +
|
|
739
|
+
variant.toString() +
|
|
740
|
+
" this.dataType= " +
|
|
741
|
+
this.dataType.toString()
|
|
742
|
+
);
|
|
773
743
|
}
|
|
774
|
-
if (
|
|
775
|
-
|
|
744
|
+
if (
|
|
745
|
+
variant.dataType === DataType.Boolean &&
|
|
746
|
+
(this.dataType.namespace !== 0 || this.dataType.value !== DataType.Boolean)
|
|
747
|
+
) {
|
|
748
|
+
throw new Error(
|
|
749
|
+
"Variant must provide a valid Boolean : variant = " +
|
|
750
|
+
variant.toString() +
|
|
751
|
+
" this.dataType= " +
|
|
752
|
+
this.dataType.toString()
|
|
753
|
+
);
|
|
776
754
|
}
|
|
777
|
-
|
|
778
755
|
if (
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
variant.dataType !== DataType.
|
|
782
|
-
variant.dataType !==
|
|
756
|
+
this.dataType.namespace === 0 &&
|
|
757
|
+
this.dataType.value === DataType.LocalizedText &&
|
|
758
|
+
variant.dataType !== DataType.LocalizedText &&
|
|
759
|
+
variant.dataType !== DataType.Null
|
|
783
760
|
) {
|
|
784
|
-
|
|
785
|
-
"
|
|
786
|
-
|
|
787
|
-
"
|
|
788
|
-
this.
|
|
789
|
-
|
|
790
|
-
this.dataType.toString() +
|
|
791
|
-
":\n" +
|
|
792
|
-
"the provided variant must have the expected dataType!\n" +
|
|
793
|
-
" - the expected dataType is " +
|
|
794
|
-
chalk.cyan(DataType[basicType]) +
|
|
795
|
-
"\n" +
|
|
796
|
-
" - the actual dataType is " +
|
|
797
|
-
chalk.magenta(DataType[variant.dataType]) +
|
|
798
|
-
"\n" +
|
|
799
|
-
" - " +
|
|
800
|
-
variant.toString();
|
|
801
|
-
throw new Error(message);
|
|
761
|
+
throw new Error(
|
|
762
|
+
"Variant must provide a valid LocalizedText : variant = " +
|
|
763
|
+
variant.toString() +
|
|
764
|
+
" this.dataType= " +
|
|
765
|
+
this.dataType.toString()
|
|
766
|
+
);
|
|
802
767
|
}
|
|
803
|
-
} catch (err) {
|
|
804
|
-
errorLog("UAVariable ", (err as Error)?.message, this.browseName.toString(), " nodeId=", this.nodeId.toString());
|
|
805
|
-
errorLog((err as Error).message);
|
|
806
|
-
errorLog((err as Error).stack);
|
|
807
|
-
throw err;
|
|
808
768
|
}
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
. *
|
|
814
|
-
* The method will raise an exception if the value is not compatible with the dataType and expected dimension
|
|
815
|
-
*
|
|
816
|
-
* @method setValueFromSource
|
|
817
|
-
* @param variant {Variant}
|
|
818
|
-
* @param [statusCode {StatusCode} = StatusCodes.Good]
|
|
819
|
-
* @param [sourceTimestamp= Now]
|
|
820
|
-
*/
|
|
821
|
-
public setValueFromSource(variant: VariantLike, statusCode?: StatusCode, sourceTimestamp?: Date): void {
|
|
822
|
-
try {
|
|
823
|
-
statusCode = statusCode || StatusCodes.Good;
|
|
824
|
-
const variant1 = Variant.coerce(variant);
|
|
825
|
-
this.verifyVariantCompatibility(variant1);
|
|
826
|
-
const now = coerceClock(sourceTimestamp, 0);
|
|
827
|
-
|
|
828
|
-
const dataValue = new DataValue(null);
|
|
829
|
-
dataValue.serverPicoseconds = now.picoseconds;
|
|
830
|
-
dataValue.serverTimestamp = now.timestamp;
|
|
831
|
-
dataValue.sourcePicoseconds = now.picoseconds;
|
|
832
|
-
dataValue.sourceTimestamp = now.timestamp;
|
|
833
|
-
dataValue.statusCode = statusCode;
|
|
834
|
-
dataValue.value = variant1;
|
|
835
|
-
|
|
836
|
-
if (dataValue.value.dataType === DataType.ExtensionObject) {
|
|
837
|
-
const valueIsCorrect = this.checkExtensionObjectIsCorrect(dataValue.value.value);
|
|
838
|
-
if (!valueIsCorrect) {
|
|
839
|
-
errorLog("setValueFromSource Invalid value !");
|
|
840
|
-
errorLog(this.toString());
|
|
841
|
-
errorLog(dataValue.toString());
|
|
842
|
-
this.checkExtensionObjectIsCorrect(dataValue.value.value);
|
|
843
|
-
}
|
|
844
|
-
// ----------------------------------
|
|
845
|
-
if (this.$extensionObject || this.$$extensionObjectArray) {
|
|
846
|
-
// we have an extension object already bound to this node
|
|
847
|
-
// the client is asking us to replace the object entierly by a new one
|
|
848
|
-
// const ext = dataValue.value.value;
|
|
849
|
-
this._internal_set_dataValue(dataValue);
|
|
850
|
-
return;
|
|
851
|
-
} else {
|
|
852
|
-
this.$dataValue = dataValue;
|
|
853
|
-
}
|
|
854
|
-
} else {
|
|
855
|
-
this._internal_set_dataValue(dataValue);
|
|
856
|
-
}
|
|
857
|
-
} catch (err) {
|
|
858
|
-
errorLog("UAVariable#setValueFromString Error : ", this.browseName.toString(), this.nodeId.toString());
|
|
859
|
-
errorLog((err as Error).message);
|
|
860
|
-
errorLog(this.parent?.toString());
|
|
861
|
-
throw err;
|
|
769
|
+
const basicType = this.getBasicDataType();
|
|
770
|
+
|
|
771
|
+
if (basicType === DataType.String && variant.dataType === DataType.ByteString) {
|
|
772
|
+
return; // this is allowed
|
|
862
773
|
}
|
|
774
|
+
if (basicType === DataType.ByteString && variant.dataType === DataType.String) {
|
|
775
|
+
return; // this is allowed
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
if (
|
|
779
|
+
basicType !== DataType.Null &&
|
|
780
|
+
basicType !== DataType.Variant &&
|
|
781
|
+
variant.dataType !== DataType.Null &&
|
|
782
|
+
variant.dataType !== basicType
|
|
783
|
+
) {
|
|
784
|
+
const message =
|
|
785
|
+
"UAVariable.setValueFromSource " +
|
|
786
|
+
this.browseName.toString() +
|
|
787
|
+
" nodeId:" +
|
|
788
|
+
this.nodeId.toString() +
|
|
789
|
+
" dataType:" +
|
|
790
|
+
this.dataType.toString() +
|
|
791
|
+
":\n" +
|
|
792
|
+
"the provided variant must have the expected dataType!\n" +
|
|
793
|
+
" - the expected dataType is " +
|
|
794
|
+
chalk.cyan(DataType[basicType]) +
|
|
795
|
+
"\n" +
|
|
796
|
+
" - the actual dataType is " +
|
|
797
|
+
chalk.magenta(DataType[variant.dataType]) +
|
|
798
|
+
"\n" +
|
|
799
|
+
" - " +
|
|
800
|
+
variant.toString();
|
|
801
|
+
throw new Error(message);
|
|
802
|
+
}
|
|
803
|
+
} catch (err) {
|
|
804
|
+
errorLog("UAVariable ", (err as Error)?.message, this.browseName.toString(), " nodeId=", this.nodeId.toString());
|
|
805
|
+
errorLog((err as Error).message);
|
|
806
|
+
errorLog((err as Error).stack);
|
|
807
|
+
throw err;
|
|
863
808
|
}
|
|
809
|
+
}
|
|
810
|
+
/**
|
|
811
|
+
* setValueFromSource is used to let the device sets the variable values
|
|
812
|
+
* this method also records the current time as sourceTimestamp and serverTimestamp.
|
|
813
|
+
. *
|
|
814
|
+
* The method will raise an exception if the value is not compatible with the dataType and expected dimension
|
|
815
|
+
*
|
|
816
|
+
* @method setValueFromSource
|
|
817
|
+
* @param variant {Variant}
|
|
818
|
+
* @param [statusCode {StatusCode} = StatusCodes.Good]
|
|
819
|
+
* @param [sourceTimestamp= Now]
|
|
820
|
+
*/
|
|
821
|
+
public setValueFromSource(variant: VariantLike, statusCode?: StatusCode, sourceTimestamp?: Date): void {
|
|
822
|
+
try {
|
|
823
|
+
statusCode = statusCode || StatusCodes.Good;
|
|
824
|
+
const variant1 = Variant.coerce(variant);
|
|
825
|
+
this.verifyVariantCompatibility(variant1);
|
|
826
|
+
const now = coerceClock(sourceTimestamp, 0);
|
|
827
|
+
|
|
828
|
+
const dataValue = new DataValue(null);
|
|
829
|
+
dataValue.serverPicoseconds = now.picoseconds;
|
|
830
|
+
dataValue.serverTimestamp = now.timestamp;
|
|
831
|
+
dataValue.sourcePicoseconds = now.picoseconds;
|
|
832
|
+
dataValue.sourceTimestamp = now.timestamp;
|
|
833
|
+
dataValue.statusCode = statusCode;
|
|
834
|
+
dataValue.value = variant1;
|
|
864
835
|
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
if (!dataValue.sourceTimestamp) {
|
|
882
|
-
// source timestamp was not specified by the caller
|
|
883
|
-
// we will set the timestamp ourself with the current clock
|
|
884
|
-
if (context.currentTime) {
|
|
885
|
-
dataValue.sourceTimestamp = context.currentTime.timestamp;
|
|
886
|
-
dataValue.sourcePicoseconds = context.currentTime.picoseconds;
|
|
836
|
+
if (dataValue.value.dataType === DataType.ExtensionObject) {
|
|
837
|
+
const valueIsCorrect = this.checkExtensionObjectIsCorrect(dataValue.value.value);
|
|
838
|
+
if (!valueIsCorrect) {
|
|
839
|
+
errorLog("setValueFromSource Invalid value !");
|
|
840
|
+
errorLog(this.toString());
|
|
841
|
+
errorLog(dataValue.toString());
|
|
842
|
+
this.checkExtensionObjectIsCorrect(dataValue.value.value);
|
|
843
|
+
}
|
|
844
|
+
// ----------------------------------
|
|
845
|
+
if (this.$extensionObject || this.$$extensionObjectArray) {
|
|
846
|
+
// we have an extension object already bound to this node
|
|
847
|
+
// the client is asking us to replace the object entierly by a new one
|
|
848
|
+
// const ext = dataValue.value.value;
|
|
849
|
+
this._internal_set_dataValue(dataValue);
|
|
850
|
+
return;
|
|
887
851
|
} else {
|
|
888
|
-
|
|
889
|
-
dataValue.sourceTimestamp = timestamp;
|
|
890
|
-
dataValue.sourcePicoseconds = picoseconds;
|
|
852
|
+
this.$dataValue = dataValue;
|
|
891
853
|
}
|
|
854
|
+
} else {
|
|
855
|
+
this._internal_set_dataValue(dataValue);
|
|
892
856
|
}
|
|
857
|
+
} catch (err) {
|
|
858
|
+
errorLog("UAVariable#setValueFromString Error : ", this.browseName.toString(), this.nodeId.toString());
|
|
859
|
+
errorLog((err as Error).message);
|
|
860
|
+
errorLog(this.parent?.toString());
|
|
861
|
+
throw err;
|
|
862
|
+
}
|
|
863
|
+
}
|
|
893
864
|
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
865
|
+
public writeValue(
|
|
866
|
+
context: ISessionContext,
|
|
867
|
+
dataValue: DataValue,
|
|
868
|
+
indexRange: string | NumericRange | null,
|
|
869
|
+
callback: StatusCodeCallback
|
|
870
|
+
): void;
|
|
871
|
+
public writeValue(context: ISessionContext, dataValue: DataValue, callback: StatusCodeCallback): void;
|
|
872
|
+
public writeValue(
|
|
873
|
+
context: ISessionContext,
|
|
874
|
+
dataValue: DataValue,
|
|
875
|
+
indexRange?: string | NumericRange | null
|
|
876
|
+
): Promise<StatusCode>;
|
|
877
|
+
public writeValue(context: ISessionContext, dataValue: DataValue, ...args: any[]): any {
|
|
878
|
+
context = context || SessionContext.defaultContext;
|
|
879
|
+
assert(context instanceof SessionContext);
|
|
898
880
|
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
if (
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
} else if (args.length === 2) {
|
|
906
|
-
indexRange = args[0];
|
|
907
|
-
callback = args[1];
|
|
881
|
+
if (!dataValue.sourceTimestamp) {
|
|
882
|
+
// source timestamp was not specified by the caller
|
|
883
|
+
// we will set the timestamp ourself with the current clock
|
|
884
|
+
if (context.currentTime) {
|
|
885
|
+
dataValue.sourceTimestamp = context.currentTime.timestamp;
|
|
886
|
+
dataValue.sourcePicoseconds = context.currentTime.picoseconds;
|
|
908
887
|
} else {
|
|
909
|
-
|
|
888
|
+
const { timestamp, picoseconds } = getCurrentClock();
|
|
889
|
+
dataValue.sourceTimestamp = timestamp;
|
|
890
|
+
dataValue.sourcePicoseconds = picoseconds;
|
|
910
891
|
}
|
|
892
|
+
}
|
|
911
893
|
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
894
|
+
if (context.currentTime && !dataValue.serverTimestamp) {
|
|
895
|
+
dataValue.serverTimestamp = context.currentTime.timestamp;
|
|
896
|
+
dataValue.serverPicoseconds = context.currentTime.picoseconds;
|
|
897
|
+
}
|
|
916
898
|
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
899
|
+
// adjust arguments if optional indexRange Parameter is not given
|
|
900
|
+
let indexRange: NumericRange | null = null;
|
|
901
|
+
let callback: StatusCodeCallback;
|
|
902
|
+
if (args.length === 1) {
|
|
903
|
+
indexRange = new NumericRange();
|
|
904
|
+
callback = args[0];
|
|
905
|
+
} else if (args.length === 2) {
|
|
906
|
+
indexRange = args[0];
|
|
907
|
+
callback = args[1];
|
|
908
|
+
} else {
|
|
909
|
+
throw new Error("Invalid Number of args");
|
|
910
|
+
}
|
|
924
911
|
|
|
912
|
+
assert(typeof callback === "function");
|
|
913
|
+
assert(dataValue instanceof DataValue);
|
|
914
|
+
// index range could be string
|
|
915
|
+
indexRange = NumericRange.coerce(indexRange);
|
|
925
916
|
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
917
|
+
// test write permission
|
|
918
|
+
if (!this.isWritable(context)) {
|
|
919
|
+
return callback!(null, StatusCodes.BadNotWritable);
|
|
920
|
+
}
|
|
921
|
+
if (!this.checkPermissionPrivate(context, PermissionType.Write)) {
|
|
922
|
+
return new DataValue({ statusCode: StatusCodes.BadUserAccessDenied });
|
|
923
|
+
}
|
|
929
924
|
|
|
930
|
-
// adjust special case
|
|
931
|
-
const variant = adjustVariant2.call(this, dataValue.value);
|
|
932
925
|
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
}
|
|
926
|
+
if (!this.isUserWritable(context)) {
|
|
927
|
+
return callback!(null, StatusCodes.BadWriteNotSupported);
|
|
928
|
+
}
|
|
937
929
|
|
|
938
|
-
|
|
930
|
+
// adjust special case
|
|
931
|
+
const variant = adjustVariant2.call(this, dataValue.value);
|
|
939
932
|
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
933
|
+
const statusCode = this.checkVariantCompatibility(variant);
|
|
934
|
+
if (statusCode.isNot(StatusCodes.Good)) {
|
|
935
|
+
return callback!(null, statusCode);
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
const write_func = this._timestamped_set_func || default_func;
|
|
939
|
+
|
|
940
|
+
if (!write_func) {
|
|
941
|
+
warningLog(" warning " + this.nodeId.toString() + " " + this.browseName.toString() + " has no setter. \n");
|
|
942
|
+
warningLog("Please make sure to bind the variable or to pass a valid value: new Variant({}) during construction time");
|
|
943
|
+
return callback!(null, StatusCodes.BadNotWritable);
|
|
944
|
+
}
|
|
945
|
+
assert(write_func);
|
|
946
946
|
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
947
|
+
write_func.call(this, dataValue, (err?: Error | null, statusCode1?: StatusCode) => {
|
|
948
|
+
if (!err) {
|
|
949
|
+
dataValue && this.verifyVariantCompatibility(dataValue.value);
|
|
950
950
|
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
951
|
+
if (indexRange && !indexRange.isEmpty()) {
|
|
952
|
+
if (!indexRange.isValid()) {
|
|
953
|
+
return callback!(null, StatusCodes.BadIndexRangeInvalid);
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
const newArrayOrMatrix = dataValue.value.value;
|
|
957
|
+
|
|
958
|
+
if (dataValue.value.arrayType === VariantArrayType.Array) {
|
|
959
|
+
if (this.$dataValue.value.arrayType !== VariantArrayType.Array) {
|
|
960
|
+
return callback(null, StatusCodes.BadTypeMismatch);
|
|
954
961
|
}
|
|
962
|
+
// check that destination data is also an array
|
|
963
|
+
assert(check_valid_array(this.$dataValue.value.dataType, this.$dataValue.value.value));
|
|
964
|
+
const destArr = this.$dataValue.value.value;
|
|
965
|
+
const result = indexRange.set_values(destArr, newArrayOrMatrix);
|
|
955
966
|
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
if (result.statusCode.isNot(StatusCodes.Good)) {
|
|
968
|
-
return callback!(null, result.statusCode);
|
|
969
|
-
}
|
|
970
|
-
dataValue.value.value = result.array;
|
|
971
|
-
|
|
972
|
-
// scrap original array so we detect range
|
|
973
|
-
this.$dataValue.value.value = null;
|
|
974
|
-
} else if (dataValue.value.arrayType === VariantArrayType.Matrix) {
|
|
975
|
-
const dimensions = this.$dataValue.value.dimensions;
|
|
976
|
-
if (this.$dataValue.value.arrayType !== VariantArrayType.Matrix || !dimensions) {
|
|
977
|
-
// not a matrix !
|
|
978
|
-
return callback!(null, StatusCodes.BadTypeMismatch);
|
|
979
|
-
}
|
|
980
|
-
const matrix = this.$dataValue.value.value;
|
|
981
|
-
const result = indexRange.set_values_matrix(
|
|
982
|
-
{
|
|
983
|
-
matrix,
|
|
984
|
-
dimensions
|
|
985
|
-
},
|
|
986
|
-
newArrayOrMatrix
|
|
987
|
-
);
|
|
988
|
-
if (result.statusCode.isNot(StatusCodes.Good)) {
|
|
989
|
-
return callback!(null, result.statusCode);
|
|
990
|
-
}
|
|
991
|
-
dataValue.value.dimensions = this.$dataValue.value.dimensions;
|
|
992
|
-
dataValue.value.value = result.matrix;
|
|
993
|
-
|
|
994
|
-
// scrap original array so we detect range
|
|
995
|
-
this.$dataValue.value.value = null;
|
|
996
|
-
} else {
|
|
967
|
+
if (result.statusCode.isNot(StatusCodes.Good)) {
|
|
968
|
+
return callback!(null, result.statusCode);
|
|
969
|
+
}
|
|
970
|
+
dataValue.value.value = result.array;
|
|
971
|
+
|
|
972
|
+
// scrap original array so we detect range
|
|
973
|
+
this.$dataValue.value.value = null;
|
|
974
|
+
} else if (dataValue.value.arrayType === VariantArrayType.Matrix) {
|
|
975
|
+
const dimensions = this.$dataValue.value.dimensions;
|
|
976
|
+
if (this.$dataValue.value.arrayType !== VariantArrayType.Matrix || !dimensions) {
|
|
977
|
+
// not a matrix !
|
|
997
978
|
return callback!(null, StatusCodes.BadTypeMismatch);
|
|
998
979
|
}
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
980
|
+
const matrix = this.$dataValue.value.value;
|
|
981
|
+
const result = indexRange.set_values_matrix(
|
|
982
|
+
{
|
|
983
|
+
matrix,
|
|
984
|
+
dimensions
|
|
985
|
+
},
|
|
986
|
+
newArrayOrMatrix
|
|
987
|
+
);
|
|
988
|
+
if (result.statusCode.isNot(StatusCodes.Good)) {
|
|
989
|
+
return callback!(null, result.statusCode);
|
|
1005
990
|
}
|
|
1006
|
-
|
|
991
|
+
dataValue.value.dimensions = this.$dataValue.value.dimensions;
|
|
992
|
+
dataValue.value.value = result.matrix;
|
|
993
|
+
|
|
994
|
+
// scrap original array so we detect range
|
|
995
|
+
this.$dataValue.value.value = null;
|
|
996
|
+
} else {
|
|
997
|
+
return callback!(null, StatusCodes.BadTypeMismatch);
|
|
1007
998
|
}
|
|
1008
999
|
}
|
|
1009
|
-
|
|
1010
|
-
|
|
1000
|
+
try {
|
|
1001
|
+
this._internal_set_dataValue(dataValue, indexRange);
|
|
1002
|
+
} catch (err) {
|
|
1003
|
+
if (err instanceof Error) {
|
|
1004
|
+
warningLog(err.message);
|
|
1005
|
+
}
|
|
1006
|
+
return callback!(null, StatusCodes.BadInternalError);
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
1009
|
+
callback!(err || null, statusCode1);
|
|
1010
|
+
});
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1013
|
+
public writeAttribute(context: ISessionContext | null, writeValue: WriteValueOptions, callback: StatusCodeCallback): void;
|
|
1014
|
+
public writeAttribute(context: ISessionContext | null, writeValue: WriteValueOptions): Promise<StatusCode>;
|
|
1015
|
+
public writeAttribute(
|
|
1016
|
+
context: ISessionContext | null,
|
|
1017
|
+
writeValueOptions: WriteValueOptions,
|
|
1018
|
+
callback?: (err: Error | null, statusCode?: StatusCode) => void
|
|
1019
|
+
): any {
|
|
1020
|
+
// istanbul ignore next
|
|
1021
|
+
if (!callback) {
|
|
1022
|
+
throw new Error("Internal error");
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
if (!this.canUserWriteAttribute(context, writeValueOptions.attributeId!)) {
|
|
1026
|
+
return callback(null, StatusCodes.BadUserAccessDenied);
|
|
1027
|
+
}
|
|
1028
|
+
const writeValue: WriteValue =
|
|
1029
|
+
writeValueOptions instanceof WriteValue ? (writeValueOptions as WriteValue) : new WriteValue(writeValueOptions);
|
|
1030
|
+
|
|
1031
|
+
context = context || SessionContext.defaultContext;
|
|
1032
|
+
|
|
1033
|
+
assert(context instanceof SessionContext);
|
|
1034
|
+
assert(writeValue instanceof WriteValue);
|
|
1035
|
+
assert(writeValue.value instanceof DataValue);
|
|
1036
|
+
assert(writeValue.value!.value instanceof Variant);
|
|
1037
|
+
assert(typeof callback === "function");
|
|
1038
|
+
|
|
1039
|
+
// Spec 1.0.2 Part 4 page 58
|
|
1040
|
+
// If the SourceTimestamp or the ServerTimestamp is specified, the Server shall
|
|
1041
|
+
// use these values.
|
|
1042
|
+
|
|
1043
|
+
// xx _apply_default_timestamps(writeValue.value);
|
|
1044
|
+
|
|
1045
|
+
switch (writeValue.attributeId) {
|
|
1046
|
+
case AttributeIds.Value:
|
|
1047
|
+
this.writeValue(context, writeValue.value!, writeValue.indexRange!, callback);
|
|
1048
|
+
break;
|
|
1049
|
+
case AttributeIds.Historizing:
|
|
1050
|
+
if (writeValue.value!.value.dataType !== DataType.Boolean) {
|
|
1051
|
+
return callback(null, StatusCodes.BadTypeMismatch);
|
|
1052
|
+
}
|
|
1053
|
+
if (!this.checkPermissionPrivate(context, PermissionType.WriteHistorizing)) {
|
|
1054
|
+
return callback(null, StatusCodes.BadUserAccessDenied);
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1057
|
+
if (!this.canUserWriteHistorizingAttribute(context)) {
|
|
1058
|
+
return callback(null, StatusCodes.BadHistoryOperationUnsupported);
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1061
|
+
// if the variable has no historizing in place reject
|
|
1062
|
+
if (!this.getChildByName("HA Configuration")) {
|
|
1063
|
+
return callback(null, StatusCodes.BadNotSupported);
|
|
1064
|
+
}
|
|
1065
|
+
// check if user is allowed to do that !
|
|
1066
|
+
// TODO
|
|
1067
|
+
this.historizing = !!writeValue.value!.value.value; // yes ! indeed !
|
|
1068
|
+
return callback(null, StatusCodes.Good);
|
|
1069
|
+
|
|
1070
|
+
default:
|
|
1071
|
+
super.writeAttribute(context, writeValue, callback);
|
|
1072
|
+
break;
|
|
1011
1073
|
}
|
|
1074
|
+
}
|
|
1012
1075
|
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1076
|
+
/**
|
|
1077
|
+
* @method checkVariantCompatibility
|
|
1078
|
+
* note:
|
|
1079
|
+
* this method is overridden in address-space-data-access
|
|
1080
|
+
* @return {StatusCode}
|
|
1081
|
+
*/
|
|
1082
|
+
public checkVariantCompatibility(value: Variant): StatusCode {
|
|
1083
|
+
// test dataType
|
|
1084
|
+
if (!this._validate_DataType(value.dataType)) {
|
|
1085
|
+
return StatusCodes.BadTypeMismatch;
|
|
1086
|
+
}
|
|
1087
|
+
try {
|
|
1088
|
+
this.verifyVariantCompatibility(value);
|
|
1089
|
+
} catch (err) {
|
|
1090
|
+
return StatusCodes.BadTypeMismatch;
|
|
1091
|
+
}
|
|
1092
|
+
return StatusCodes.Good;
|
|
1093
|
+
}
|
|
1024
1094
|
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
assert(context instanceof SessionContext);
|
|
1034
|
-
assert(writeValue instanceof WriteValue);
|
|
1035
|
-
assert(writeValue.value instanceof DataValue);
|
|
1036
|
-
assert(writeValue.value!.value instanceof Variant);
|
|
1037
|
-
assert(typeof callback === "function");
|
|
1038
|
-
|
|
1039
|
-
// Spec 1.0.2 Part 4 page 58
|
|
1040
|
-
// If the SourceTimestamp or the ServerTimestamp is specified, the Server shall
|
|
1041
|
-
// use these values.
|
|
1042
|
-
|
|
1043
|
-
// xx _apply_default_timestamps(writeValue.value);
|
|
1044
|
-
|
|
1045
|
-
switch (writeValue.attributeId) {
|
|
1046
|
-
case AttributeIds.Value:
|
|
1047
|
-
this.writeValue(context, writeValue.value!, writeValue.indexRange!, callback);
|
|
1048
|
-
break;
|
|
1049
|
-
case AttributeIds.Historizing:
|
|
1050
|
-
if (writeValue.value!.value.dataType !== DataType.Boolean) {
|
|
1051
|
-
return callback(null, StatusCodes.BadTypeMismatch);
|
|
1052
|
-
}
|
|
1053
|
-
if (!this.checkPermissionPrivate(context, PermissionType.WriteHistorizing)) {
|
|
1054
|
-
return callback(null, StatusCodes.BadUserAccessDenied);
|
|
1055
|
-
}
|
|
1095
|
+
/**
|
|
1096
|
+
* touch the source timestamp of a Variable and cascade up the change
|
|
1097
|
+
* to the parent variable if any.
|
|
1098
|
+
*/
|
|
1099
|
+
public touchValue(optionalNow?: PreciseClock): void {
|
|
1100
|
+
const now = optionalNow || getCurrentClock();
|
|
1101
|
+
propagateTouchValueUpward(this, now);
|
|
1102
|
+
}
|
|
1056
1103
|
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1104
|
+
/**
|
|
1105
|
+
* bind a variable with a get and set functions.
|
|
1106
|
+
*
|
|
1107
|
+
* properties:
|
|
1108
|
+
* - value: a Variant or a status code
|
|
1109
|
+
* - sourceTimestamp
|
|
1110
|
+
* - sourcePicoseconds
|
|
1111
|
+
* @param [options.timestamped_set]
|
|
1112
|
+
* @param [options.refreshFunc] the variable asynchronous getter function.
|
|
1113
|
+
* @param [overwrite {Boolean} = false] set overwrite to true to overwrite existing binding
|
|
1114
|
+
* @return void
|
|
1115
|
+
*
|
|
1116
|
+
*
|
|
1117
|
+
* ### Providing read access to the underlying value
|
|
1118
|
+
*
|
|
1119
|
+
* #### Variation 1
|
|
1120
|
+
*
|
|
1121
|
+
* In this variation, the user provides a function that returns a Variant with the current value.
|
|
1122
|
+
*
|
|
1123
|
+
* The sourceTimestamp will be set automatically.
|
|
1124
|
+
*
|
|
1125
|
+
* The get function is called synchronously.
|
|
1126
|
+
*
|
|
1127
|
+
* @example
|
|
1128
|
+
*
|
|
1129
|
+
*
|
|
1130
|
+
* ```javascript
|
|
1131
|
+
* ...
|
|
1132
|
+
* var options = {
|
|
1133
|
+
* get : () => {
|
|
1134
|
+
* return new Variant({...});
|
|
1135
|
+
* },
|
|
1136
|
+
* set : function(variant) {
|
|
1137
|
+
* // store the variant somewhere
|
|
1138
|
+
* return StatusCodes.Good;
|
|
1139
|
+
* }
|
|
1140
|
+
* };
|
|
1141
|
+
* ...
|
|
1142
|
+
* engine.bindVariable(nodeId,options):
|
|
1143
|
+
* ...
|
|
1144
|
+
* ```
|
|
1145
|
+
*
|
|
1146
|
+
*
|
|
1147
|
+
* #### Variation 2:
|
|
1148
|
+
*
|
|
1149
|
+
* This variation can be used when the user wants to specify a specific '''sourceTimestamp''' associated
|
|
1150
|
+
* with the current value of the UAVariable.
|
|
1151
|
+
*
|
|
1152
|
+
* The provided ```timestamped_get``` function should return an object with three properties:
|
|
1153
|
+
* * value: containing the variant value or a error StatusCode,
|
|
1154
|
+
* * sourceTimestamp
|
|
1155
|
+
* * sourcePicoseconds
|
|
1156
|
+
*
|
|
1157
|
+
* ```javascript
|
|
1158
|
+
* ...
|
|
1159
|
+
* var myDataValue = new DataValue({
|
|
1160
|
+
* value: {dataType: DataType.Double , value: 10.0},
|
|
1161
|
+
* sourceTimestamp : new Date(),
|
|
1162
|
+
* sourcePicoseconds: 0
|
|
1163
|
+
* });
|
|
1164
|
+
* ...
|
|
1165
|
+
* var options = {
|
|
1166
|
+
* timestamped_get : () => { return myDataValue; }
|
|
1167
|
+
* };
|
|
1168
|
+
* ...
|
|
1169
|
+
* engine.bindVariable(nodeId,options):
|
|
1170
|
+
* ...
|
|
1171
|
+
* // record a new value
|
|
1172
|
+
* myDataValue.value.value = 5.0;
|
|
1173
|
+
* myDataValue.sourceTimestamp = new Date();
|
|
1174
|
+
* ...
|
|
1175
|
+
* ```
|
|
1176
|
+
*
|
|
1177
|
+
*
|
|
1178
|
+
* #### Variation 3:
|
|
1179
|
+
*
|
|
1180
|
+
* This variation can be used when the value associated with the variables requires a asynchronous function call to be
|
|
1181
|
+
* extracted. In this case, the user should provide an async method ```refreshFunc```.
|
|
1182
|
+
*
|
|
1183
|
+
*
|
|
1184
|
+
* The ```refreshFunc``` shall do whatever is necessary to fetch the most up to date version of the variable value, and
|
|
1185
|
+
* call the ```callback``` function when the data is ready.
|
|
1186
|
+
*
|
|
1187
|
+
*
|
|
1188
|
+
* The ```callback``` function follow the standard callback function signature:
|
|
1189
|
+
* * the first argument shall be **null** or **Error**, depending of the outcome of the fetch operation,
|
|
1190
|
+
* * the second argument shall be a DataValue with the new UAVariable Value, a StatusCode, and time stamps.
|
|
1191
|
+
*
|
|
1192
|
+
*
|
|
1193
|
+
* Optionally, it is possible to pass a sourceTimestamp and a sourcePicoseconds value as a third and fourth arguments
|
|
1194
|
+
* of the callback. When sourceTimestamp and sourcePicoseconds are missing, the system will set their default value
|
|
1195
|
+
* to the current time..
|
|
1196
|
+
*
|
|
1197
|
+
*
|
|
1198
|
+
* ```javascript
|
|
1199
|
+
* ...
|
|
1200
|
+
* var options = {
|
|
1201
|
+
* refreshFunc : function(callback) {
|
|
1202
|
+
* ... do_some_async_stuff_to_get_the_new_variable_value
|
|
1203
|
+
* var dataValue = new DataValue({
|
|
1204
|
+
* value: new Variant({...}),
|
|
1205
|
+
* statusCode: StatusCodes.Good,
|
|
1206
|
+
* sourceTimestamp: new Date()
|
|
1207
|
+
* });
|
|
1208
|
+
* callback(null,dataValue);
|
|
1209
|
+
* }
|
|
1210
|
+
* };
|
|
1211
|
+
* ...
|
|
1212
|
+
* variable.bindVariable(nodeId,options):
|
|
1213
|
+
* ...
|
|
1214
|
+
* ```
|
|
1215
|
+
*
|
|
1216
|
+
* ### Providing write access to the underlying value
|
|
1217
|
+
*
|
|
1218
|
+
* #### Variation1 - provide a simple synchronous set function
|
|
1219
|
+
*
|
|
1220
|
+
*
|
|
1221
|
+
* #### Notes
|
|
1222
|
+
* to do : explain return StatusCodes.GoodCompletesAsynchronously;
|
|
1223
|
+
*
|
|
1224
|
+
*/
|
|
1225
|
+
public bindVariable(options?: BindVariableOptions, overwrite?: boolean): void {
|
|
1226
|
+
if (overwrite) {
|
|
1227
|
+
this._timestamped_set_func = null;
|
|
1228
|
+
this._timestamped_get_func = null;
|
|
1229
|
+
this._get_func = null;
|
|
1230
|
+
this._set_func = null;
|
|
1231
|
+
this.refreshFunc = undefined;
|
|
1232
|
+
this._historyRead = UAVariableImpl.prototype._historyRead;
|
|
1233
|
+
}
|
|
1060
1234
|
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1235
|
+
options = options || {};
|
|
1236
|
+
|
|
1237
|
+
assert(typeof this._timestamped_set_func !== "function", "UAVariable already bound");
|
|
1238
|
+
assert(typeof this._timestamped_get_func !== "function", "UAVariable already bound");
|
|
1239
|
+
|
|
1240
|
+
bind_getter.call(this, options);
|
|
1241
|
+
bind_setter.call(this, options);
|
|
1242
|
+
|
|
1243
|
+
const _historyRead = options.historyRead;
|
|
1244
|
+
if (_historyRead) {
|
|
1245
|
+
assert(typeof this._historyRead !== "function" || this._historyRead === UAVariableImpl.prototype._historyRead);
|
|
1246
|
+
assert(typeof _historyRead === "function");
|
|
1247
|
+
|
|
1248
|
+
this._historyRead = _historyRead;
|
|
1249
|
+
assert(this._historyRead.length === 6);
|
|
1074
1250
|
}
|
|
1251
|
+
// post conditions
|
|
1252
|
+
assert(typeof this._timestamped_set_func === "function");
|
|
1253
|
+
assert(this._timestamped_set_func!.length === 2, "expecting 2 parameters");
|
|
1254
|
+
}
|
|
1075
1255
|
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
public checkVariantCompatibility(value: Variant): StatusCode {
|
|
1083
|
-
// test dataType
|
|
1084
|
-
if (!this._validate_DataType(value.dataType)) {
|
|
1085
|
-
return StatusCodes.BadTypeMismatch;
|
|
1086
|
-
}
|
|
1087
|
-
try {
|
|
1088
|
-
this.verifyVariantCompatibility(value);
|
|
1089
|
-
} catch (err) {
|
|
1090
|
-
return StatusCodes.BadTypeMismatch;
|
|
1091
|
-
}
|
|
1092
|
-
return StatusCodes.Good;
|
|
1093
|
-
}
|
|
1094
|
-
|
|
1095
|
-
/**
|
|
1096
|
-
* touch the source timestamp of a Variable and cascade up the change
|
|
1097
|
-
* to the parent variable if any.
|
|
1098
|
-
*/
|
|
1099
|
-
public touchValue(optionalNow?: PreciseClock): void {
|
|
1100
|
-
const now = optionalNow || getCurrentClock();
|
|
1101
|
-
propagateTouchValueUpward(this, now);
|
|
1102
|
-
}
|
|
1103
|
-
|
|
1104
|
-
/**
|
|
1105
|
-
* bind a variable with a get and set functions.
|
|
1106
|
-
*
|
|
1107
|
-
* properties:
|
|
1108
|
-
* - value: a Variant or a status code
|
|
1109
|
-
* - sourceTimestamp
|
|
1110
|
-
* - sourcePicoseconds
|
|
1111
|
-
* @param [options.timestamped_set]
|
|
1112
|
-
* @param [options.refreshFunc] the variable asynchronous getter function.
|
|
1113
|
-
* @param [overwrite {Boolean} = false] set overwrite to true to overwrite existing binding
|
|
1114
|
-
* @return void
|
|
1115
|
-
*
|
|
1116
|
-
*
|
|
1117
|
-
* ### Providing read access to the underlying value
|
|
1118
|
-
*
|
|
1119
|
-
* #### Variation 1
|
|
1120
|
-
*
|
|
1121
|
-
* In this variation, the user provides a function that returns a Variant with the current value.
|
|
1122
|
-
*
|
|
1123
|
-
* The sourceTimestamp will be set automatically.
|
|
1124
|
-
*
|
|
1125
|
-
* The get function is called synchronously.
|
|
1126
|
-
*
|
|
1127
|
-
* @example
|
|
1128
|
-
*
|
|
1129
|
-
*
|
|
1130
|
-
* ```javascript
|
|
1131
|
-
* ...
|
|
1132
|
-
* var options = {
|
|
1133
|
-
* get : () => {
|
|
1134
|
-
* return new Variant({...});
|
|
1135
|
-
* },
|
|
1136
|
-
* set : function(variant) {
|
|
1137
|
-
* // store the variant somewhere
|
|
1138
|
-
* return StatusCodes.Good;
|
|
1139
|
-
* }
|
|
1140
|
-
* };
|
|
1141
|
-
* ...
|
|
1142
|
-
* engine.bindVariable(nodeId,options):
|
|
1143
|
-
* ...
|
|
1144
|
-
* ```
|
|
1145
|
-
*
|
|
1146
|
-
*
|
|
1147
|
-
* #### Variation 2:
|
|
1148
|
-
*
|
|
1149
|
-
* This variation can be used when the user wants to specify a specific '''sourceTimestamp''' associated
|
|
1150
|
-
* with the current value of the UAVariable.
|
|
1151
|
-
*
|
|
1152
|
-
* The provided ```timestamped_get``` function should return an object with three properties:
|
|
1153
|
-
* * value: containing the variant value or a error StatusCode,
|
|
1154
|
-
* * sourceTimestamp
|
|
1155
|
-
* * sourcePicoseconds
|
|
1156
|
-
*
|
|
1157
|
-
* ```javascript
|
|
1158
|
-
* ...
|
|
1159
|
-
* var myDataValue = new DataValue({
|
|
1160
|
-
* value: {dataType: DataType.Double , value: 10.0},
|
|
1161
|
-
* sourceTimestamp : new Date(),
|
|
1162
|
-
* sourcePicoseconds: 0
|
|
1163
|
-
* });
|
|
1164
|
-
* ...
|
|
1165
|
-
* var options = {
|
|
1166
|
-
* timestamped_get : () => { return myDataValue; }
|
|
1167
|
-
* };
|
|
1168
|
-
* ...
|
|
1169
|
-
* engine.bindVariable(nodeId,options):
|
|
1170
|
-
* ...
|
|
1171
|
-
* // record a new value
|
|
1172
|
-
* myDataValue.value.value = 5.0;
|
|
1173
|
-
* myDataValue.sourceTimestamp = new Date();
|
|
1174
|
-
* ...
|
|
1175
|
-
* ```
|
|
1176
|
-
*
|
|
1177
|
-
*
|
|
1178
|
-
* #### Variation 3:
|
|
1179
|
-
*
|
|
1180
|
-
* This variation can be used when the value associated with the variables requires a asynchronous function call to be
|
|
1181
|
-
* extracted. In this case, the user should provide an async method ```refreshFunc```.
|
|
1182
|
-
*
|
|
1183
|
-
*
|
|
1184
|
-
* The ```refreshFunc``` shall do whatever is necessary to fetch the most up to date version of the variable value, and
|
|
1185
|
-
* call the ```callback``` function when the data is ready.
|
|
1186
|
-
*
|
|
1187
|
-
*
|
|
1188
|
-
* The ```callback``` function follow the standard callback function signature:
|
|
1189
|
-
* * the first argument shall be **null** or **Error**, depending of the outcome of the fetch operation,
|
|
1190
|
-
* * the second argument shall be a DataValue with the new UAVariable Value, a StatusCode, and time stamps.
|
|
1191
|
-
*
|
|
1192
|
-
*
|
|
1193
|
-
* Optionally, it is possible to pass a sourceTimestamp and a sourcePicoseconds value as a third and fourth arguments
|
|
1194
|
-
* of the callback. When sourceTimestamp and sourcePicoseconds are missing, the system will set their default value
|
|
1195
|
-
* to the current time..
|
|
1196
|
-
*
|
|
1197
|
-
*
|
|
1198
|
-
* ```javascript
|
|
1199
|
-
* ...
|
|
1200
|
-
* var options = {
|
|
1201
|
-
* refreshFunc : function(callback) {
|
|
1202
|
-
* ... do_some_async_stuff_to_get_the_new_variable_value
|
|
1203
|
-
* var dataValue = new DataValue({
|
|
1204
|
-
* value: new Variant({...}),
|
|
1205
|
-
* statusCode: StatusCodes.Good,
|
|
1206
|
-
* sourceTimestamp: new Date()
|
|
1207
|
-
* });
|
|
1208
|
-
* callback(null,dataValue);
|
|
1209
|
-
* }
|
|
1210
|
-
* };
|
|
1211
|
-
* ...
|
|
1212
|
-
* variable.bindVariable(nodeId,options):
|
|
1213
|
-
* ...
|
|
1214
|
-
* ```
|
|
1215
|
-
*
|
|
1216
|
-
* ### Providing write access to the underlying value
|
|
1217
|
-
*
|
|
1218
|
-
* #### Variation1 - provide a simple synchronous set function
|
|
1219
|
-
*
|
|
1220
|
-
*
|
|
1221
|
-
* #### Notes
|
|
1222
|
-
* to do : explain return StatusCodes.GoodCompletesAsynchronously;
|
|
1223
|
-
*
|
|
1224
|
-
*/
|
|
1225
|
-
public bindVariable(options?: BindVariableOptions, overwrite?: boolean): void {
|
|
1226
|
-
if (overwrite) {
|
|
1227
|
-
this._timestamped_set_func = null;
|
|
1228
|
-
this._timestamped_get_func = null;
|
|
1229
|
-
this._get_func = null;
|
|
1230
|
-
this._set_func = null;
|
|
1231
|
-
this.refreshFunc = undefined;
|
|
1232
|
-
this._historyRead = UAVariableImpl.prototype._historyRead;
|
|
1233
|
-
}
|
|
1256
|
+
/**
|
|
1257
|
+
* @method readValueAsync
|
|
1258
|
+
*/
|
|
1259
|
+
public readValueAsync(context: ISessionContext | null, callback: CallbackT<DataValue>): void;
|
|
1260
|
+
public readValueAsync(context: ISessionContext | null): Promise<DataValue>;
|
|
1261
|
+
public readValueAsync(context: ISessionContext | null, callback?: CallbackT<DataValue>): any {
|
|
1234
1262
|
|
|
1235
|
-
|
|
1263
|
+
assert(typeof callback === "function");
|
|
1236
1264
|
|
|
1237
|
-
|
|
1238
|
-
assert(typeof this._timestamped_get_func !== "function", "UAVariable already bound");
|
|
1265
|
+
context = context || SessionContext.defaultContext;
|
|
1239
1266
|
|
|
1240
|
-
|
|
1241
|
-
|
|
1267
|
+
this.__waiting_callbacks = this.__waiting_callbacks || [];
|
|
1268
|
+
this.__waiting_callbacks.push(callback);
|
|
1242
1269
|
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1270
|
+
const _readValueAsync_in_progress = this.__waiting_callbacks.length >= 2;
|
|
1271
|
+
if (_readValueAsync_in_progress) {
|
|
1272
|
+
return;
|
|
1273
|
+
}
|
|
1247
1274
|
|
|
1248
|
-
|
|
1249
|
-
assert(this._historyRead.length === 6);
|
|
1250
|
-
}
|
|
1251
|
-
// post conditions
|
|
1252
|
-
assert(typeof this._timestamped_set_func === "function");
|
|
1253
|
-
assert(this._timestamped_set_func!.length === 2, "expecting 2 parameters");
|
|
1254
|
-
}
|
|
1255
|
-
|
|
1256
|
-
/**
|
|
1257
|
-
* @method readValueAsync
|
|
1258
|
-
*/
|
|
1259
|
-
public readValueAsync(context: ISessionContext | null, callback: CallbackT<DataValue>): void;
|
|
1260
|
-
public readValueAsync(context: ISessionContext | null): Promise<DataValue>;
|
|
1261
|
-
public readValueAsync(context: ISessionContext | null, callback?: CallbackT<DataValue>): any {
|
|
1262
|
-
if (!context) {
|
|
1263
|
-
context = SessionContext.defaultContext;
|
|
1264
|
-
}
|
|
1265
|
-
assert(typeof callback === "function");
|
|
1275
|
+
if (this.isDisposed()) { return callback!(null, new DataValue({ statusCode: StatusCodes.BadNodeIdUnknown })); }
|
|
1266
1276
|
|
|
1267
|
-
|
|
1268
|
-
this
|
|
1277
|
+
const readImmediate = (innerCallback: (err: Error | null, dataValue: DataValue) => void) => {
|
|
1278
|
+
assert(this.$dataValue instanceof DataValue);
|
|
1279
|
+
const dataValue = this.readValue();
|
|
1280
|
+
innerCallback(null, dataValue);
|
|
1281
|
+
};
|
|
1269
1282
|
|
|
1270
|
-
|
|
1271
|
-
if (_readValueAsync_in_progress) {
|
|
1272
|
-
return;
|
|
1273
|
-
}
|
|
1283
|
+
let func: (innerCallback: (err: Error | null, dataValue: DataValue) => void) => void;
|
|
1274
1284
|
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
const dataValue =
|
|
1285
|
+
if (!this.isReadable(context)) {
|
|
1286
|
+
func = (innerCallback: (err: Error | null, dataValue: DataValue) => void) => {
|
|
1287
|
+
const dataValue = new DataValue({ statusCode: StatusCodes.BadNotReadable });
|
|
1278
1288
|
innerCallback(null, dataValue);
|
|
1279
1289
|
};
|
|
1290
|
+
} else if (!this.checkPermissionPrivate(context, PermissionType.Read)) {
|
|
1291
|
+
func = (innerCallback: (err: Error | null, dataValue: DataValue) => void) => {
|
|
1292
|
+
const dataValue = new DataValue({ statusCode: StatusCodes.BadUserAccessDenied });
|
|
1293
|
+
innerCallback(null, dataValue);
|
|
1294
|
+
};
|
|
1295
|
+
} else if (!this.isUserReadable(context)) {
|
|
1296
|
+
func = (innerCallback: (err: Error | null, dataValue: DataValue) => void) => {
|
|
1297
|
+
const dataValue = new DataValue({ statusCode: StatusCodes.BadNotReadable });
|
|
1298
|
+
innerCallback(null, dataValue);
|
|
1299
|
+
};
|
|
1300
|
+
} else {
|
|
1301
|
+
func = typeof this.refreshFunc === "function" ? this.asyncRefresh.bind(this, new Date()) : readImmediate;
|
|
1302
|
+
}
|
|
1280
1303
|
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
} else if (!this.checkPermissionPrivate(context, PermissionType.Read)) {
|
|
1289
|
-
func = (innerCallback: (err: Error | null, dataValue: DataValue) => void) => {
|
|
1290
|
-
const dataValue = new DataValue({ statusCode: StatusCodes.BadUserAccessDenied });
|
|
1291
|
-
innerCallback(null, dataValue);
|
|
1292
|
-
};
|
|
1293
|
-
} else if (!this.isUserReadable(context)) {
|
|
1294
|
-
func = (innerCallback: (err: Error | null, dataValue: DataValue) => void) => {
|
|
1295
|
-
const dataValue = new DataValue({ statusCode: StatusCodes.BadNotReadable });
|
|
1296
|
-
innerCallback(null, dataValue);
|
|
1297
|
-
};
|
|
1298
|
-
} else {
|
|
1299
|
-
func = typeof this.refreshFunc === "function" ? this.asyncRefresh.bind(this, new Date()) : readImmediate;
|
|
1300
|
-
}
|
|
1301
|
-
|
|
1302
|
-
const satisfy_callbacks = (err: Error | null, dataValue?: DataValue) => {
|
|
1303
|
-
// now call all pending callbacks
|
|
1304
|
-
const callbacks = this.__waiting_callbacks || [];
|
|
1305
|
-
this.__waiting_callbacks = [];
|
|
1306
|
-
const n = callbacks.length;
|
|
1307
|
-
for (const callback1 of callbacks) {
|
|
1308
|
-
callback1.call(this, err, dataValue);
|
|
1304
|
+
const satisfy_callbacks = (err: Error | null, dataValue?: DataValue) => {
|
|
1305
|
+
// now call all pending callbacks
|
|
1306
|
+
const callbacks = this.__waiting_callbacks || [];
|
|
1307
|
+
this.__waiting_callbacks = [];
|
|
1308
|
+
const n = callbacks.length;
|
|
1309
|
+
for (const callback1 of callbacks) {
|
|
1310
|
+
callback1.call(this, err, dataValue);
|
|
1309
1311
|
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
+
}
|
|
1313
|
+
};
|
|
1312
1314
|
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
}
|
|
1315
|
+
try {
|
|
1316
|
+
func.call(this, satisfy_callbacks);
|
|
1317
|
+
} catch (err) {
|
|
1318
|
+
// istanbul ignore next
|
|
1319
|
+
if (doDebug) {
|
|
1320
|
+
debugLog(chalk.red("func readValueAsync has failed "));
|
|
1321
|
+
if (err instanceof Error) {
|
|
1322
|
+
debugLog(" stack", err.stack);
|
|
1322
1323
|
}
|
|
1323
|
-
satisfy_callbacks(err as Error);
|
|
1324
1324
|
}
|
|
1325
|
+
satisfy_callbacks(err as Error);
|
|
1325
1326
|
}
|
|
1327
|
+
}
|
|
1326
1328
|
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
public getUserWriteMask(): number {
|
|
1332
|
-
return super.getUserWriteMask();
|
|
1333
|
-
}
|
|
1329
|
+
public getWriteMask(): number {
|
|
1330
|
+
return super.getWriteMask();
|
|
1331
|
+
}
|
|
1334
1332
|
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
// check this eventNotifier: this.eventNotifier,
|
|
1339
|
-
// check this symbolicName: this.symbolicName,
|
|
1333
|
+
public getUserWriteMask(): number {
|
|
1334
|
+
return super.getUserWriteMask();
|
|
1335
|
+
}
|
|
1340
1336
|
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1337
|
+
public clone(options: CloneOptions, optionalFilter?: CloneFilter, extraInfo?: CloneExtraInfo): UAVariable {
|
|
1338
|
+
options = {
|
|
1339
|
+
...options,
|
|
1340
|
+
// check this eventNotifier: this.eventNotifier,
|
|
1341
|
+
// check this symbolicName: this.symbolicName,
|
|
1342
|
+
|
|
1343
|
+
accessLevel: this.accessLevel,
|
|
1344
|
+
arrayDimensions: this.arrayDimensions,
|
|
1345
|
+
dataType: this.dataType,
|
|
1346
|
+
historizing: this.historizing,
|
|
1347
|
+
minimumSamplingInterval: this.minimumSamplingInterval,
|
|
1348
|
+
userAccessLevel: this.userAccessLevel,
|
|
1349
|
+
valueRank: this.valueRank
|
|
1350
|
+
};
|
|
1349
1351
|
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1352
|
+
const newVariable = _clone.call(
|
|
1353
|
+
this,
|
|
1354
|
+
UAVariableImpl,
|
|
1355
|
+
options,
|
|
1356
|
+
optionalFilter || defaultCloneFilter,
|
|
1357
|
+
extraInfo || defaultCloneExtraInfo
|
|
1358
|
+
) as UAVariableImpl;
|
|
1357
1359
|
|
|
1358
|
-
|
|
1360
|
+
newVariable.bindVariable();
|
|
1359
1361
|
|
|
1360
|
-
|
|
1362
|
+
assert(typeof newVariable._timestamped_set_func === "function");
|
|
1361
1363
|
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
+
assert(newVariable.dataType === this.dataType);
|
|
1365
|
+
newVariable.$dataValue = this.$dataValue.clone();
|
|
1364
1366
|
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
}
|
|
1367
|
+
// also bind extension object
|
|
1368
|
+
const v = newVariable.$dataValue.value;
|
|
1369
|
+
if (v.dataType === DataType.ExtensionObject && v.value && v.arrayType === VariantArrayType.Scalar) {
|
|
1370
|
+
try {
|
|
1371
|
+
newVariable.bindExtensionObject(newVariable.$dataValue.value.value);
|
|
1372
|
+
} catch (err) {
|
|
1373
|
+
errorLog("Errro binding extension objects");
|
|
1374
|
+
errorLog((err as Error).message);
|
|
1375
|
+
errorLog(this.toString());
|
|
1376
|
+
errorLog("---------------------------------------");
|
|
1377
|
+
errorLog(this.$dataValue.toString());
|
|
1378
|
+
errorLog("---------------------------------------");
|
|
1379
|
+
errorLog(newVariable.$dataValue.toString());
|
|
1380
|
+
throw err;
|
|
1380
1381
|
}
|
|
1381
|
-
return newVariable;
|
|
1382
1382
|
}
|
|
1383
|
+
return newVariable;
|
|
1384
|
+
}
|
|
1383
1385
|
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
}
|
|
1391
|
-
return dt as UADataType;
|
|
1386
|
+
public getDataTypeNode(): UADataType {
|
|
1387
|
+
const addressSpace = this.addressSpace;
|
|
1388
|
+
const dt = addressSpace.findNode(this.dataType);
|
|
1389
|
+
// istanbul ignore next
|
|
1390
|
+
if (!dt) {
|
|
1391
|
+
throw new Error("getDataTypeNode: cannot find dataType " + this.dataType.toString());
|
|
1392
1392
|
}
|
|
1393
|
+
return dt as UADataType;
|
|
1394
|
+
}
|
|
1393
1395
|
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1396
|
+
public get dataTypeObj(): UADataType {
|
|
1397
|
+
return this.getDataTypeNode();
|
|
1398
|
+
}
|
|
1397
1399
|
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1400
|
+
public checkExtensionObjectIsCorrect(extObj: ExtensionObject | ExtensionObject[] | null): boolean {
|
|
1401
|
+
if (!extObj) {
|
|
1402
|
+
return true;
|
|
1403
|
+
}
|
|
1404
|
+
const addressSpace = this.addressSpace;
|
|
1405
|
+
const dataType = addressSpace.findDataType(this.dataType);
|
|
1406
|
+
if (!dataType) {
|
|
1407
|
+
// may be we are in the process of loading a xml file and the corresponding dataType
|
|
1408
|
+
// has not yet been loaded !
|
|
1409
|
+
return true;
|
|
1410
|
+
}
|
|
1409
1411
|
|
|
1410
|
-
|
|
1412
|
+
const Constructor = addressSpace.getExtensionObjectConstructor(this.dataType);
|
|
1411
1413
|
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1414
|
+
if (this.valueRank === -1) {
|
|
1415
|
+
/** Scalar */
|
|
1416
|
+
if (extObj instanceof Array) {
|
|
1417
|
+
return false;
|
|
1418
|
+
}
|
|
1419
|
+
return checkExtensionObjectIsCorrectScalar.call(this, extObj);
|
|
1420
|
+
} else if (this.valueRank >= 1) {
|
|
1421
|
+
/** array */
|
|
1422
|
+
if (!(extObj instanceof Array)) {
|
|
1423
|
+
// let's coerce this scalar into an 1-element array if it is a valid extension object
|
|
1424
|
+
if (checkExtensionObjectIsCorrectScalar.call(this, extObj)) {
|
|
1425
|
+
warningLog(
|
|
1426
|
+
`warning: checkExtensionObjectIsCorrect : expecting a array but got a scalar (value rank of '${this.browseName.toString()}' is 1)\nautomatic conversion from scalar to array with 1 element is taking place.`
|
|
1427
|
+
);
|
|
1428
|
+
extObj = [extObj];
|
|
1429
|
+
} else {
|
|
1415
1430
|
return false;
|
|
1416
1431
|
}
|
|
1417
|
-
return checkExtensionObjectIsCorrectScalar.call(this, extObj);
|
|
1418
|
-
} else if (this.valueRank >= 1) {
|
|
1419
|
-
/** array */
|
|
1420
|
-
if (!(extObj instanceof Array)) {
|
|
1421
|
-
// let's coerce this scalar into an 1-element array if it is a valid extension object
|
|
1422
|
-
if (checkExtensionObjectIsCorrectScalar.call(this, extObj)) {
|
|
1423
|
-
warningLog(
|
|
1424
|
-
`warning: checkExtensionObjectIsCorrect : expecting a array but got a scalar (value rank of '${this.browseName.toString()}' is 1)\nautomatic conversion from scalar to array with 1 element is taking place.`
|
|
1425
|
-
);
|
|
1426
|
-
extObj = [extObj];
|
|
1427
|
-
} else {
|
|
1428
|
-
return false;
|
|
1429
|
-
}
|
|
1430
|
-
}
|
|
1431
|
-
return checkExtensionObjectIsCorrectArray.call(this, extObj);
|
|
1432
|
-
} else if (this.valueRank === 0) {
|
|
1433
|
-
// Scalar or Array
|
|
1434
|
-
const isCorrectScalar = !Array.isArray(extObj) && checkExtensionObjectIsCorrectScalar.call(this, extObj);
|
|
1435
|
-
const isCorrectArray =
|
|
1436
|
-
Array.isArray(extObj) && checkExtensionObjectIsCorrectArray.call(this, extObj as ExtensionObject[]);
|
|
1437
|
-
return isCorrectArray || isCorrectScalar;
|
|
1438
|
-
} else {
|
|
1439
|
-
throw new Error(
|
|
1440
|
-
`checkExtensionObjectIsCorrect: Not Implemented case, please contact sterfive : this.valueRank =${this.valueRank}`
|
|
1441
|
-
);
|
|
1442
1432
|
}
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
)
|
|
1447
|
-
|
|
1433
|
+
return checkExtensionObjectIsCorrectArray.call(this, extObj);
|
|
1434
|
+
} else if (this.valueRank === 0) {
|
|
1435
|
+
// Scalar or Array
|
|
1436
|
+
const isCorrectScalar = !Array.isArray(extObj) && checkExtensionObjectIsCorrectScalar.call(this, extObj);
|
|
1437
|
+
const isCorrectArray =
|
|
1438
|
+
Array.isArray(extObj) && checkExtensionObjectIsCorrectArray.call(this, extObj as ExtensionObject[]);
|
|
1439
|
+
return isCorrectArray || isCorrectScalar;
|
|
1440
|
+
} else {
|
|
1441
|
+
throw new Error(
|
|
1442
|
+
`checkExtensionObjectIsCorrect: Not Implemented case, please contact sterfive : this.valueRank =${this.valueRank}`
|
|
1443
|
+
);
|
|
1444
|
+
}
|
|
1445
|
+
function checkExtensionObjectIsCorrectScalar(
|
|
1446
|
+
this: UAVariableImpl,
|
|
1447
|
+
extObj: ExtensionObject | ExtensionObject[] | null
|
|
1448
|
+
): boolean {
|
|
1449
|
+
// istanbul ignore next
|
|
1450
|
+
if (!(extObj && extObj.constructor)) {
|
|
1451
|
+
errorLog(extObj);
|
|
1452
|
+
throw new Error("expecting an valid extension object");
|
|
1453
|
+
}
|
|
1454
|
+
return extObj.constructor.name === Constructor.name;
|
|
1455
|
+
}
|
|
1456
|
+
|
|
1457
|
+
function checkExtensionObjectIsCorrectArray(this: UAVariableImpl, extObjArray: ExtensionObject[]): boolean {
|
|
1458
|
+
// istanbul ignore next
|
|
1459
|
+
for (const extObj of extObjArray) {
|
|
1448
1460
|
if (!(extObj && extObj.constructor)) {
|
|
1449
1461
|
errorLog(extObj);
|
|
1450
1462
|
throw new Error("expecting an valid extension object");
|
|
1451
1463
|
}
|
|
1452
|
-
return extObj.constructor.name === Constructor.name;
|
|
1453
1464
|
}
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
if (!(extObj && extObj.constructor)) {
|
|
1459
|
-
errorLog(extObj);
|
|
1460
|
-
throw new Error("expecting an valid extension object");
|
|
1465
|
+
try {
|
|
1466
|
+
for (const e of extObjArray) {
|
|
1467
|
+
if (!e) {
|
|
1468
|
+
continue;
|
|
1461
1469
|
}
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
if (!e) {
|
|
1466
|
-
continue;
|
|
1467
|
-
}
|
|
1468
|
-
if (e.constructor.name !== Constructor.name) {
|
|
1469
|
-
debugLog("extObj.constructor.name ", e.constructor.name, "expected", Constructor.name);
|
|
1470
|
-
return false;
|
|
1471
|
-
}
|
|
1470
|
+
if (e.constructor.name !== Constructor.name) {
|
|
1471
|
+
debugLog("extObj.constructor.name ", e.constructor.name, "expected", Constructor.name);
|
|
1472
|
+
return false;
|
|
1472
1473
|
}
|
|
1473
|
-
return true;
|
|
1474
|
-
} catch (err) {
|
|
1475
|
-
errorLog(err);
|
|
1476
|
-
return false;
|
|
1477
1474
|
}
|
|
1475
|
+
return true;
|
|
1476
|
+
} catch (err) {
|
|
1477
|
+
errorLog(err);
|
|
1478
|
+
return false;
|
|
1478
1479
|
}
|
|
1479
1480
|
}
|
|
1481
|
+
}
|
|
1480
1482
|
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
public bindExtensionObjectArray(
|
|
1503
|
-
optionalExtensionObject?: ExtensionObject[],
|
|
1504
|
-
options?: BindExtensionObjectOptions
|
|
1505
|
-
): ExtensionObject[] | null {
|
|
1506
|
-
assert(this.valueRank >= 1, "expecting an Array or a Matrix variable here");
|
|
1507
|
-
return _bindExtensionObjectArrayOrMatrix(this, optionalExtensionObject, options);
|
|
1508
|
-
}
|
|
1509
|
-
|
|
1510
|
-
public bindExtensionObject(
|
|
1511
|
-
optionalExtensionObject?: ExtensionObject | ExtensionObject[],
|
|
1512
|
-
options?: BindExtensionObjectOptions
|
|
1513
|
-
): ExtensionObject | ExtensionObject[] | null {
|
|
1514
|
-
|
|
1515
|
-
// coerce to ExtensionObject[] when this.valueRank === 1
|
|
1516
|
-
if (optionalExtensionObject && this.valueRank === 1 && !Array.isArray(optionalExtensionObject) && optionalExtensionObject instanceof ExtensionObject) {
|
|
1517
|
-
warningLog("bindExtensionObject: coerce to ExtensionObject[] when valueRank === 1 and value is a scalar extension object");
|
|
1518
|
-
optionalExtensionObject = [optionalExtensionObject];
|
|
1519
|
-
}
|
|
1483
|
+
/**
|
|
1484
|
+
* @private
|
|
1485
|
+
* install UAVariable to exposed th
|
|
1486
|
+
*
|
|
1487
|
+
* precondition:
|
|
1488
|
+
*/
|
|
1489
|
+
public installExtensionObjectVariables(): void {
|
|
1490
|
+
_installExtensionObjectBindingOnProperties(this, { createMissingProp: true });
|
|
1491
|
+
}
|
|
1492
|
+
/**
|
|
1493
|
+
* @method bindExtensionObject
|
|
1494
|
+
* @return {ExtensionObject}
|
|
1495
|
+
*/
|
|
1496
|
+
public bindExtensionObjectScalar(
|
|
1497
|
+
optionalExtensionObject?: ExtensionObject,
|
|
1498
|
+
options?: BindExtensionObjectOptions
|
|
1499
|
+
): ExtensionObject | null {
|
|
1500
|
+
assert(this.valueRank === -1, "expecting an Scalar variable here");
|
|
1501
|
+
return _bindExtensionObject(this, optionalExtensionObject, options) as ExtensionObject;
|
|
1502
|
+
}
|
|
1520
1503
|
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1504
|
+
public bindExtensionObjectArray(
|
|
1505
|
+
optionalExtensionObject?: ExtensionObject[],
|
|
1506
|
+
options?: BindExtensionObjectOptions
|
|
1507
|
+
): ExtensionObject[] | null {
|
|
1508
|
+
assert(this.valueRank >= 1, "expecting an Array or a Matrix variable here");
|
|
1509
|
+
return _bindExtensionObjectArrayOrMatrix(this, optionalExtensionObject, options);
|
|
1510
|
+
}
|
|
1511
|
+
|
|
1512
|
+
public bindExtensionObject(
|
|
1513
|
+
optionalExtensionObject?: ExtensionObject | ExtensionObject[],
|
|
1514
|
+
options?: BindExtensionObjectOptions
|
|
1515
|
+
): ExtensionObject | ExtensionObject[] | null {
|
|
1516
|
+
|
|
1517
|
+
// coerce to ExtensionObject[] when this.valueRank === 1
|
|
1518
|
+
if (optionalExtensionObject && this.valueRank === 1 && !Array.isArray(optionalExtensionObject) && optionalExtensionObject instanceof ExtensionObject) {
|
|
1519
|
+
warningLog("bindExtensionObject: coerce to ExtensionObject[] when valueRank === 1 and value is a scalar extension object");
|
|
1520
|
+
optionalExtensionObject = [optionalExtensionObject];
|
|
1521
|
+
}
|
|
1522
|
+
|
|
1523
|
+
if (optionalExtensionObject) {
|
|
1524
|
+
if (optionalExtensionObject instanceof Array) {
|
|
1525
|
+
assert(this.valueRank >= 1, "bindExtensionObject: expecting an Array of Matrix variable here");
|
|
1526
|
+
return _bindExtensionObjectArrayOrMatrix(this, optionalExtensionObject, options);
|
|
1527
|
+
} else {
|
|
1528
|
+
if (this.valueRank !== -1 && this.valueRank !== 0) {
|
|
1529
|
+
throw new Error("bindExtensionObject: expecting an Scalar variable here but got value rank " + this.valueRank);
|
|
1530
1530
|
}
|
|
1531
|
+
return _bindExtensionObject(this, optionalExtensionObject, options) as ExtensionObject;
|
|
1531
1532
|
}
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
public updateExtensionObjectPartial(partialExtensionObject?: { [key: string]: any }): ExtensionObject {
|
|
1545
|
-
setExtensionObjectPartialValue(this, partialExtensionObject);
|
|
1546
|
-
return this.$extensionObject;
|
|
1547
|
-
}
|
|
1548
|
-
|
|
1549
|
-
public incrementExtensionObjectPartial(path: string | string[]): void {
|
|
1550
|
-
const extensionObject = this.readValue().value.value as ExtensionObject;
|
|
1551
|
-
const partialData = extractPartialData(path, extensionObject);
|
|
1552
|
-
incrementElement(path, partialData);
|
|
1553
|
-
setExtensionObjectPartialValue(this, partialData);
|
|
1554
|
-
}
|
|
1555
|
-
|
|
1556
|
-
public toString(): string {
|
|
1557
|
-
const options = new ToStringBuilder();
|
|
1558
|
-
UAVariable_toString.call(this, options);
|
|
1559
|
-
return options.toString();
|
|
1560
|
-
}
|
|
1561
|
-
|
|
1562
|
-
// ---------------------------------------------------------------------------------------------------
|
|
1563
|
-
// History
|
|
1564
|
-
// ---------------------------------------------------------------------------------------------------
|
|
1565
|
-
|
|
1566
|
-
public historyRead(
|
|
1567
|
-
context: ISessionContext,
|
|
1568
|
-
historyReadDetails:
|
|
1569
|
-
| HistoryReadDetails
|
|
1570
|
-
| ReadRawModifiedDetails
|
|
1571
|
-
| ReadEventDetails
|
|
1572
|
-
| ReadProcessedDetails
|
|
1573
|
-
| ReadAtTimeDetails,
|
|
1574
|
-
indexRange: NumericRange | null,
|
|
1575
|
-
dataEncoding: QualifiedNameLike | null,
|
|
1576
|
-
continuationData: ContinuationData
|
|
1577
|
-
): Promise<HistoryReadResult>;
|
|
1578
|
-
|
|
1579
|
-
public historyRead(
|
|
1580
|
-
context: ISessionContext,
|
|
1581
|
-
historyReadDetails:
|
|
1582
|
-
| HistoryReadDetails
|
|
1583
|
-
| ReadRawModifiedDetails
|
|
1584
|
-
| ReadEventDetails
|
|
1585
|
-
| ReadProcessedDetails
|
|
1586
|
-
| ReadAtTimeDetails,
|
|
1587
|
-
indexRange: NumericRange | null,
|
|
1588
|
-
dataEncoding: QualifiedNameLike | null,
|
|
1589
|
-
continuationData: ContinuationData,
|
|
1590
|
-
callback: CallbackT<HistoryReadResult>
|
|
1591
|
-
): void;
|
|
1592
|
-
public historyRead(
|
|
1593
|
-
context: ISessionContext,
|
|
1594
|
-
historyReadDetails:
|
|
1595
|
-
| HistoryReadDetails
|
|
1596
|
-
| ReadRawModifiedDetails
|
|
1597
|
-
| ReadEventDetails
|
|
1598
|
-
| ReadProcessedDetails
|
|
1599
|
-
| ReadAtTimeDetails,
|
|
1600
|
-
indexRange: NumericRange | null,
|
|
1601
|
-
dataEncoding: QualifiedNameLike | null,
|
|
1602
|
-
continuationData: ContinuationData,
|
|
1603
|
-
callback?: CallbackT<HistoryReadResult>
|
|
1604
|
-
): any {
|
|
1605
|
-
assert(context instanceof SessionContext);
|
|
1606
|
-
assert(typeof callback === "function");
|
|
1607
|
-
if (typeof this._historyRead !== "function") {
|
|
1608
|
-
return callback!(null, new HistoryReadResult({ statusCode: StatusCodes.BadNotReadable }));
|
|
1609
|
-
}
|
|
1533
|
+
}
|
|
1534
|
+
assert(optionalExtensionObject === undefined);
|
|
1535
|
+
if (this.valueRank === -1) {
|
|
1536
|
+
return _bindExtensionObject(this, undefined, options) as ExtensionObject;
|
|
1537
|
+
} else if (this.valueRank === 1) {
|
|
1538
|
+
return _bindExtensionObjectArrayOrMatrix(this, undefined, options);
|
|
1539
|
+
} else if (this.valueRank > 1) {
|
|
1540
|
+
return _bindExtensionObjectArrayOrMatrix(this, undefined, options);
|
|
1541
|
+
}
|
|
1542
|
+
// unsupported case ...
|
|
1543
|
+
return null;
|
|
1544
|
+
}
|
|
1610
1545
|
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1546
|
+
public updateExtensionObjectPartial(partialExtensionObject?: { [key: string]: any }): ExtensionObject {
|
|
1547
|
+
setExtensionObjectPartialValue(this, partialExtensionObject);
|
|
1548
|
+
return this.$extensionObject;
|
|
1549
|
+
}
|
|
1550
|
+
|
|
1551
|
+
public incrementExtensionObjectPartial(path: string | string[]): void {
|
|
1552
|
+
const extensionObject = this.readValue().value.value as ExtensionObject;
|
|
1553
|
+
const partialData = extractPartialData(path, extensionObject);
|
|
1554
|
+
incrementElement(path, partialData);
|
|
1555
|
+
setExtensionObjectPartialValue(this, partialData);
|
|
1556
|
+
}
|
|
1557
|
+
|
|
1558
|
+
public toString(): string {
|
|
1559
|
+
const options = new ToStringBuilder();
|
|
1560
|
+
UAVariable_toString.call(this, options);
|
|
1561
|
+
return options.toString();
|
|
1562
|
+
}
|
|
1563
|
+
|
|
1564
|
+
// ---------------------------------------------------------------------------------------------------
|
|
1565
|
+
// History
|
|
1566
|
+
// ---------------------------------------------------------------------------------------------------
|
|
1567
|
+
|
|
1568
|
+
public historyRead(
|
|
1569
|
+
context: ISessionContext,
|
|
1570
|
+
historyReadDetails:
|
|
1571
|
+
| HistoryReadDetails
|
|
1572
|
+
| ReadRawModifiedDetails
|
|
1573
|
+
| ReadEventDetails
|
|
1574
|
+
| ReadProcessedDetails
|
|
1575
|
+
| ReadAtTimeDetails,
|
|
1576
|
+
indexRange: NumericRange | null,
|
|
1577
|
+
dataEncoding: QualifiedNameLike | null,
|
|
1578
|
+
continuationData: ContinuationData
|
|
1579
|
+
): Promise<HistoryReadResult>;
|
|
1580
|
+
|
|
1581
|
+
public historyRead(
|
|
1582
|
+
context: ISessionContext,
|
|
1583
|
+
historyReadDetails:
|
|
1584
|
+
| HistoryReadDetails
|
|
1585
|
+
| ReadRawModifiedDetails
|
|
1586
|
+
| ReadEventDetails
|
|
1587
|
+
| ReadProcessedDetails
|
|
1588
|
+
| ReadAtTimeDetails,
|
|
1589
|
+
indexRange: NumericRange | null,
|
|
1590
|
+
dataEncoding: QualifiedNameLike | null,
|
|
1591
|
+
continuationData: ContinuationData,
|
|
1592
|
+
callback: CallbackT<HistoryReadResult>
|
|
1593
|
+
): void;
|
|
1594
|
+
public historyRead(
|
|
1595
|
+
context: ISessionContext,
|
|
1596
|
+
historyReadDetails:
|
|
1597
|
+
| HistoryReadDetails
|
|
1598
|
+
| ReadRawModifiedDetails
|
|
1599
|
+
| ReadEventDetails
|
|
1600
|
+
| ReadProcessedDetails
|
|
1601
|
+
| ReadAtTimeDetails,
|
|
1602
|
+
indexRange: NumericRange | null,
|
|
1603
|
+
dataEncoding: QualifiedNameLike | null,
|
|
1604
|
+
continuationData: ContinuationData,
|
|
1605
|
+
callback?: CallbackT<HistoryReadResult>
|
|
1606
|
+
): any {
|
|
1607
|
+
assert(context instanceof SessionContext);
|
|
1608
|
+
assert(typeof callback === "function");
|
|
1609
|
+
if (typeof this._historyRead !== "function") {
|
|
1610
|
+
return callback!(null, new HistoryReadResult({ statusCode: StatusCodes.BadNotReadable }));
|
|
1611
|
+
}
|
|
1612
|
+
|
|
1613
|
+
this._historyRead(context, historyReadDetails, indexRange, dataEncoding, continuationData, callback!);
|
|
1614
|
+
}
|
|
1615
|
+
|
|
1616
|
+
public _historyReadRaw(
|
|
1617
|
+
context: ISessionContext,
|
|
1618
|
+
historyReadRawModifiedDetails: ReadRawModifiedDetails,
|
|
1619
|
+
indexRange: NumericRange | null,
|
|
1620
|
+
dataEncoding: QualifiedNameLike | null,
|
|
1621
|
+
continuationData: ContinuationData,
|
|
1622
|
+
callback: CallbackT<HistoryReadResult>
|
|
1623
|
+
): void {
|
|
1624
|
+
throw new Error("");
|
|
1625
|
+
}
|
|
1626
|
+
|
|
1627
|
+
public _historyReadRawModify(
|
|
1628
|
+
context: ISessionContext,
|
|
1629
|
+
historyReadRawModifiedDetails: ReadRawModifiedDetails,
|
|
1630
|
+
indexRange: NumericRange | null,
|
|
1631
|
+
dataEncoding: QualifiedNameLike | null,
|
|
1632
|
+
continuationData: ContinuationData,
|
|
1633
|
+
callback?: CallbackT<HistoryReadResult>
|
|
1634
|
+
): any {
|
|
1635
|
+
throw new Error("");
|
|
1636
|
+
}
|
|
1637
|
+
|
|
1638
|
+
public _historyRead(
|
|
1639
|
+
context: ISessionContext,
|
|
1640
|
+
historyReadDetails:
|
|
1641
|
+
| HistoryReadDetails
|
|
1642
|
+
| ReadRawModifiedDetails
|
|
1643
|
+
| ReadEventDetails
|
|
1644
|
+
| ReadProcessedDetails
|
|
1645
|
+
| ReadAtTimeDetails,
|
|
1646
|
+
indexRange: NumericRange | null,
|
|
1647
|
+
dataEncoding: QualifiedNameLike | null,
|
|
1648
|
+
continuationData: ContinuationData,
|
|
1649
|
+
callback: CallbackT<HistoryReadResult>
|
|
1650
|
+
): void {
|
|
1651
|
+
|
|
1652
|
+
if (!this.checkPermissionPrivate(context, PermissionType.ReadHistory)) {
|
|
1653
|
+
const result = new HistoryReadResult({
|
|
1654
|
+
statusCode: StatusCodes.BadUserAccessDenied
|
|
1655
|
+
});
|
|
1656
|
+
callback(null, result);
|
|
1657
|
+
}
|
|
1658
|
+
if (!this.canUserReadHistory(context)) {
|
|
1662
1659
|
const result = new HistoryReadResult({
|
|
1663
1660
|
statusCode: StatusCodes.BadHistoryOperationUnsupported
|
|
1664
1661
|
});
|
|
1665
1662
|
callback(null, result);
|
|
1666
1663
|
}
|
|
1664
|
+
const result = new HistoryReadResult({
|
|
1665
|
+
statusCode: StatusCodes.BadHistoryOperationUnsupported
|
|
1666
|
+
});
|
|
1667
|
+
callback(null, result);
|
|
1668
|
+
}
|
|
1667
1669
|
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1670
|
+
public _historyPush(newDataValue: DataValue): any {
|
|
1671
|
+
throw new Error("");
|
|
1672
|
+
}
|
|
1671
1673
|
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1674
|
+
public _historyReadRawAsync(
|
|
1675
|
+
historyReadRawModifiedDetails: ReadRawModifiedDetails,
|
|
1676
|
+
maxNumberToExtract: number,
|
|
1677
|
+
isReversed: boolean,
|
|
1678
|
+
reverseDataValue: boolean,
|
|
1679
|
+
callback: CallbackT<DataValue[]>
|
|
1680
|
+
): any {
|
|
1681
|
+
throw new Error("");
|
|
1682
|
+
}
|
|
1681
1683
|
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1684
|
+
public _historyReadModify(
|
|
1685
|
+
context: ISessionContext,
|
|
1686
|
+
historyReadRawModifiedDetails: ReadRawModifiedDetails,
|
|
1687
|
+
indexRange: NumericRange | null,
|
|
1688
|
+
dataEncoding: QualifiedNameLike | null,
|
|
1689
|
+
continuationData: ContinuationData,
|
|
1690
|
+
callback: CallbackT<HistoryReadResult>
|
|
1691
|
+
): any {
|
|
1692
|
+
throw new Error("");
|
|
1693
|
+
}
|
|
1692
1694
|
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1695
|
+
public _update_startOfOnlineArchive(newDate: Date): void {
|
|
1696
|
+
// please install
|
|
1697
|
+
throw new Error("");
|
|
1698
|
+
}
|
|
1697
1699
|
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1700
|
+
public _update_startOfArchive(newDate: Date): void {
|
|
1701
|
+
throw new Error("");
|
|
1702
|
+
}
|
|
1701
1703
|
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1704
|
+
public _validate_DataType(variantDataType: DataType): boolean {
|
|
1705
|
+
return validateDataType(this.addressSpace, this.dataType, variantDataType, this.nodeId, /* allow Nulls */ false);
|
|
1706
|
+
}
|
|
1705
1707
|
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
}
|
|
1710
|
-
this.$dataValue.value = value;
|
|
1708
|
+
public _internal_set_value(value: Variant): void {
|
|
1709
|
+
if (value.dataType !== DataType.Null) {
|
|
1710
|
+
this.verifyVariantCompatibility(value);
|
|
1711
1711
|
}
|
|
1712
|
+
this.$dataValue.value = value;
|
|
1713
|
+
}
|
|
1712
1714
|
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1715
|
+
public _internal_set_dataValue(dataValue: DataValue, indexRange?: NumericRange | null): void {
|
|
1716
|
+
assert(dataValue, "expecting a dataValue");
|
|
1717
|
+
assert(dataValue instanceof DataValue, "expecting dataValue to be a DataValue");
|
|
1718
|
+
assert(dataValue !== this.$dataValue, "expecting dataValue to be different from previous DataValue instance");
|
|
1717
1719
|
|
|
1718
|
-
|
|
1720
|
+
const addressSpace = this.addressSpace;
|
|
1719
1721
|
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1722
|
+
// istanbul ignore next
|
|
1723
|
+
if (!addressSpace) {
|
|
1724
|
+
warningLog("UAVariable#_internal_set_dataValue : no addressSpace ! may be node has already been deleted ?");
|
|
1725
|
+
return;
|
|
1726
|
+
}
|
|
1725
1727
|
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
}
|
|
1731
|
-
const nbElements = dataValue.value.dimensions.reduce((acc, x) => acc * x, 1);
|
|
1732
|
-
if (dataValue.value.value.length !== 0 && dataValue.value.value.length !== nbElements) {
|
|
1733
|
-
throw new Error(
|
|
1734
|
-
`Internal Error: matrix dimension doesn't match the number of element in the array : ${dataValue.toString()} "\n expecting ${nbElements} elements but got ${dataValue.value.value.length
|
|
1735
|
-
}`
|
|
1736
|
-
);
|
|
1737
|
-
}
|
|
1728
|
+
// istanbul ignore next
|
|
1729
|
+
if (dataValue.value.arrayType === VariantArrayType.Matrix) {
|
|
1730
|
+
if (!dataValue.value.dimensions) {
|
|
1731
|
+
throw new Error("missing dimensions: a Matrix Variant needs a dimension");
|
|
1738
1732
|
}
|
|
1733
|
+
const nbElements = dataValue.value.dimensions.reduce((acc, x) => acc * x, 1);
|
|
1734
|
+
if (dataValue.value.value.length !== 0 && dataValue.value.value.length !== nbElements) {
|
|
1735
|
+
throw new Error(
|
|
1736
|
+
`Internal Error: matrix dimension doesn't match the number of element in the array : ${dataValue.toString()} "\n expecting ${nbElements} elements but got ${dataValue.value.value.length
|
|
1737
|
+
}`
|
|
1738
|
+
);
|
|
1739
|
+
}
|
|
1740
|
+
}
|
|
1739
1741
|
|
|
1742
|
+
// istanbul ignore next
|
|
1743
|
+
if (dataValue.value.dataType === DataType.ExtensionObject) {
|
|
1740
1744
|
// istanbul ignore next
|
|
1741
|
-
if (dataValue.value.
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
warningLog(dataValue.toString());
|
|
1745
|
-
throw new Error("Invalid Extension Object on nodeId =" + this.nodeId.toString());
|
|
1746
|
-
}
|
|
1745
|
+
if (!this.checkExtensionObjectIsCorrect(dataValue.value.value)) {
|
|
1746
|
+
warningLog(dataValue.toString());
|
|
1747
|
+
throw new Error("Invalid Extension Object on nodeId =" + this.nodeId.toString());
|
|
1747
1748
|
}
|
|
1748
|
-
|
|
1749
|
-
this.verifyVariantCompatibility(dataValue.value);
|
|
1750
|
-
|
|
1751
|
-
this._inner_replace_dataValue(dataValue, indexRange);
|
|
1752
1749
|
}
|
|
1753
1750
|
|
|
1754
|
-
|
|
1755
|
-
* @private
|
|
1756
|
-
*/
|
|
1757
|
-
public _inner_replace_dataValue(dataValue: DataValue, indexRange?: NumericRange | null) {
|
|
1751
|
+
this.verifyVariantCompatibility(dataValue.value);
|
|
1758
1752
|
|
|
1759
|
-
|
|
1760
|
-
|
|
1753
|
+
this._inner_replace_dataValue(dataValue, indexRange);
|
|
1754
|
+
}
|
|
1761
1755
|
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
//
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1756
|
+
/**
|
|
1757
|
+
* @private
|
|
1758
|
+
*/
|
|
1759
|
+
public _inner_replace_dataValue(dataValue: DataValue, indexRange?: NumericRange | null) {
|
|
1760
|
+
|
|
1761
|
+
assert(this.$dataValue.value instanceof Variant);
|
|
1762
|
+
const old_dataValue = this.$dataValue.clone();
|
|
1763
|
+
|
|
1764
|
+
if (this.$$extensionObjectArray && dataValue.value.arrayType !== VariantArrayType.Scalar) {
|
|
1765
|
+
// we have a bounded array or matrix
|
|
1766
|
+
assert(Array.isArray(dataValue.value.value));
|
|
1767
|
+
if (this.$$extensionObjectArray !== this.$dataValue.value.value) {
|
|
1768
|
+
throw new Error("internal error");
|
|
1769
|
+
}
|
|
1770
|
+
this.$$extensionObjectArray = dataValue.value.value;
|
|
1771
|
+
this.$dataValue.value.value = dataValue.value.value;
|
|
1772
|
+
|
|
1773
|
+
this.$dataValue.statusCode = dataValue.statusCode || StatusCodes.Good;
|
|
1774
|
+
this.$dataValue.serverTimestamp = dataValue.serverTimestamp;
|
|
1775
|
+
this.$dataValue.serverPicoseconds = dataValue.serverPicoseconds;
|
|
1776
|
+
this.$dataValue.sourceTimestamp = dataValue.sourceTimestamp;
|
|
1777
|
+
this.$dataValue.sourcePicoseconds = dataValue.sourcePicoseconds;
|
|
1778
|
+
|
|
1779
|
+
} else if (this._basicDataType === DataType.ExtensionObject && this.valueRank === -1 && this.$set_ExtensionObject && dataValue.value.arrayType === VariantArrayType.Scalar) {
|
|
1780
|
+
// the entire extension object is changed.
|
|
1781
|
+
this.$dataValue.statusCode = this.$dataValue.statusCode || StatusCodes.Good;
|
|
1782
|
+
const preciseClock = coerceClock(this.$dataValue.sourceTimestamp, this.$dataValue.sourcePicoseconds);
|
|
1783
|
+
this.$set_ExtensionObject(dataValue.value.value, preciseClock, new Set())
|
|
1784
|
+
} else {
|
|
1785
|
+
this.$dataValue = dataValue;
|
|
1786
|
+
this.$dataValue.statusCode = this.$dataValue.statusCode || StatusCodes.Good;
|
|
1787
|
+
}
|
|
1788
|
+
// repair missing timestamps
|
|
1789
|
+
const now = new Date();
|
|
1790
|
+
if (!dataValue.serverTimestamp) {
|
|
1791
|
+
this.$dataValue.serverTimestamp = old_dataValue.serverTimestamp || now;
|
|
1792
|
+
this.$dataValue.serverPicoseconds = old_dataValue.serverPicoseconds || 0;
|
|
1793
|
+
}
|
|
1794
|
+
if (!dataValue.sourceTimestamp) {
|
|
1795
|
+
this.$dataValue.sourceTimestamp = old_dataValue.sourceTimestamp || now;
|
|
1796
|
+
this.$dataValue.sourcePicoseconds = old_dataValue.sourcePicoseconds || 0;
|
|
1797
|
+
}
|
|
1796
1798
|
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
} else {
|
|
1805
|
-
this.touchValue(preciseClock);
|
|
1806
|
-
propagateTouchValueDownward(this, preciseClock, cache);
|
|
1807
|
-
}
|
|
1799
|
+
if (!sameDataValue(old_dataValue, dataValue)) {
|
|
1800
|
+
if (this.getBasicDataType() === DataType.ExtensionObject) {
|
|
1801
|
+
const preciseClock = coerceClock(this.$dataValue.sourceTimestamp, this.$dataValue.sourcePicoseconds);
|
|
1802
|
+
const cache: Set<UAVariable> = new Set();
|
|
1803
|
+
if (this.$$extensionObjectArray) {
|
|
1804
|
+
this.touchValue(preciseClock);
|
|
1805
|
+
propagateTouchValueDownwardArray(this, preciseClock, cache);
|
|
1808
1806
|
} else {
|
|
1809
|
-
this.
|
|
1807
|
+
this.touchValue(preciseClock);
|
|
1808
|
+
propagateTouchValueDownward(this, preciseClock, cache);
|
|
1810
1809
|
}
|
|
1810
|
+
} else {
|
|
1811
|
+
this.emit("value_changed", this.$dataValue.clone(), indexRange);
|
|
1811
1812
|
}
|
|
1812
1813
|
}
|
|
1814
|
+
}
|
|
1813
1815
|
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
public handle_semantic_changed(): void {
|
|
1819
|
-
this.semantic_version = this.semantic_version + 1;
|
|
1820
|
-
this.emit("semantic_changed");
|
|
1821
|
-
}
|
|
1816
|
+
public _conditionRefresh(_cache?: ConditionRefreshCache): void {
|
|
1817
|
+
apply_condition_refresh.call(this, _cache);
|
|
1818
|
+
}
|
|
1822
1819
|
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
value: {
|
|
1828
|
-
dataType: DataType.NodeId,
|
|
1829
|
-
value: this.dataType
|
|
1830
|
-
}
|
|
1831
|
-
};
|
|
1832
|
-
return new DataValue(options);
|
|
1833
|
-
}
|
|
1820
|
+
public handle_semantic_changed(): void {
|
|
1821
|
+
this.semantic_version = this.semantic_version + 1;
|
|
1822
|
+
this.emit("semantic_changed");
|
|
1823
|
+
}
|
|
1834
1824
|
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1825
|
+
private _readDataType(): DataValue {
|
|
1826
|
+
assert(this.dataType instanceof NodeId);
|
|
1827
|
+
const options = {
|
|
1828
|
+
statusCode: StatusCodes.Good,
|
|
1829
|
+
value: {
|
|
1830
|
+
dataType: DataType.NodeId,
|
|
1831
|
+
value: this.dataType
|
|
1832
|
+
}
|
|
1833
|
+
};
|
|
1834
|
+
return new DataValue(options);
|
|
1835
|
+
}
|
|
1843
1836
|
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
}
|
|
1837
|
+
private _readValueRank(): DataValue {
|
|
1838
|
+
assert(typeof this.valueRank === "number");
|
|
1839
|
+
const options = {
|
|
1840
|
+
statusCode: StatusCodes.Good,
|
|
1841
|
+
value: { dataType: DataType.Int32, value: this.valueRank }
|
|
1842
|
+
};
|
|
1843
|
+
return new DataValue(options);
|
|
1844
|
+
}
|
|
1853
1845
|
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
}
|
|
1860
|
-
|
|
1861
|
-
|
|
1846
|
+
private _readArrayDimensions(): DataValue {
|
|
1847
|
+
assert(Array.isArray(this.arrayDimensions) || this.arrayDimensions === null);
|
|
1848
|
+
assert(!this.arrayDimensions || this.valueRank > 0, "arrayDimension must be null if valueRank <0");
|
|
1849
|
+
const options = {
|
|
1850
|
+
statusCode: StatusCodes.Good,
|
|
1851
|
+
value: { dataType: DataType.UInt32, arrayType: VariantArrayType.Array, value: this.arrayDimensions }
|
|
1852
|
+
};
|
|
1853
|
+
return new DataValue(options);
|
|
1854
|
+
}
|
|
1862
1855
|
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
}
|
|
1856
|
+
private _readAccessLevel(context: ISessionContext): DataValue {
|
|
1857
|
+
assert(context instanceof SessionContext);
|
|
1858
|
+
const options = {
|
|
1859
|
+
statusCode: StatusCodes.Good,
|
|
1860
|
+
value: { dataType: DataType.Byte, value: convertAccessLevelFlagToByte(this.accessLevel) }
|
|
1861
|
+
};
|
|
1862
|
+
return new DataValue(options);
|
|
1863
|
+
}
|
|
1872
1864
|
|
|
1873
|
-
|
|
1874
|
-
|
|
1865
|
+
private _readAccessLevelEx(context: ISessionContext): DataValue {
|
|
1866
|
+
assert(context instanceof SessionContext);
|
|
1867
|
+
const options = {
|
|
1868
|
+
statusCode: StatusCodes.Good,
|
|
1869
|
+
// Extra flags are not supported yet. to do:
|
|
1870
|
+
value: { dataType: DataType.UInt32, value: convertAccessLevelFlagToByte(this.accessLevel) }
|
|
1871
|
+
};
|
|
1872
|
+
return new DataValue(options);
|
|
1873
|
+
}
|
|
1875
1874
|
|
|
1876
|
-
|
|
1875
|
+
private _readUserAccessLevel(context: ISessionContext): DataValue {
|
|
1876
|
+
assert(context instanceof SessionContext);
|
|
1877
1877
|
|
|
1878
|
-
|
|
1879
|
-
value: {
|
|
1880
|
-
dataType: DataType.Byte,
|
|
1881
|
-
statusCode: StatusCodes.Good,
|
|
1882
|
-
value: convertAccessLevelFlagToByte(effectiveUserAccessLevel)
|
|
1883
|
-
}
|
|
1884
|
-
};
|
|
1885
|
-
return new DataValue(options);
|
|
1886
|
-
}
|
|
1878
|
+
const effectiveUserAccessLevel = _calculateEffectiveUserAccessLevelFromPermission(this, context, this.userAccessLevel);
|
|
1887
1879
|
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
} else {
|
|
1894
|
-
options.value = { dataType: DataType.Double, value: this.minimumSamplingInterval };
|
|
1895
|
-
options.statusCode = StatusCodes.Good;
|
|
1880
|
+
const options = {
|
|
1881
|
+
value: {
|
|
1882
|
+
dataType: DataType.Byte,
|
|
1883
|
+
statusCode: StatusCodes.Good,
|
|
1884
|
+
value: convertAccessLevelFlagToByte(effectiveUserAccessLevel)
|
|
1896
1885
|
}
|
|
1897
|
-
|
|
1898
|
-
|
|
1886
|
+
};
|
|
1887
|
+
return new DataValue(options);
|
|
1888
|
+
}
|
|
1899
1889
|
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1890
|
+
private _readMinimumSamplingInterval(): DataValue {
|
|
1891
|
+
// expect a Duration => Double
|
|
1892
|
+
const options: DataValueLike = {};
|
|
1893
|
+
if (this.minimumSamplingInterval === undefined) {
|
|
1894
|
+
options.statusCode = StatusCodes.BadAttributeIdInvalid;
|
|
1895
|
+
} else {
|
|
1896
|
+
options.value = { dataType: DataType.Double, value: this.minimumSamplingInterval };
|
|
1897
|
+
options.statusCode = StatusCodes.Good;
|
|
1907
1898
|
}
|
|
1899
|
+
return new DataValue(options);
|
|
1908
1900
|
}
|
|
1909
1901
|
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
export interface UAVariableImplExtArray {
|
|
1919
|
-
$$variableType?: UAVariableType;
|
|
1920
|
-
$$dataType: UADataType;
|
|
1921
|
-
$$getElementBrowseName: (extObject: ExtensionObject, index: number | number[]) => QualifiedName;
|
|
1922
|
-
$$extensionObjectArray: ExtensionObject[];
|
|
1923
|
-
$$indexPropertyName: string;
|
|
1902
|
+
private _readHistorizing(): DataValue {
|
|
1903
|
+
assert(typeof this.historizing === "boolean");
|
|
1904
|
+
const options = {
|
|
1905
|
+
statusCode: StatusCodes.Good,
|
|
1906
|
+
value: { dataType: DataType.Boolean, value: !!this.historizing }
|
|
1907
|
+
};
|
|
1908
|
+
return new DataValue(options);
|
|
1924
1909
|
}
|
|
1925
|
-
|
|
1910
|
+
}
|
|
1911
|
+
|
|
1912
|
+
// tslint:disable:no-var-requires
|
|
1913
|
+
const thenify = require("thenify");
|
|
1914
|
+
UAVariableImpl.prototype.asyncRefresh = thenify.withCallback(UAVariableImpl.prototype.asyncRefresh);
|
|
1915
|
+
UAVariableImpl.prototype.writeValue = thenify.withCallback(UAVariableImpl.prototype.writeValue);
|
|
1916
|
+
UAVariableImpl.prototype.writeAttribute = thenify.withCallback(UAVariableImpl.prototype.writeAttribute);
|
|
1917
|
+
UAVariableImpl.prototype.historyRead = thenify.withCallback(UAVariableImpl.prototype.historyRead);
|
|
1918
|
+
UAVariableImpl.prototype.readValueAsync = thenify.withCallback(UAVariableImpl.prototype.readValueAsync);
|
|
1919
|
+
|
|
1920
|
+
export interface UAVariableImplExtArray {
|
|
1921
|
+
$$variableType?: UAVariableType;
|
|
1922
|
+
$$dataType: UADataType;
|
|
1923
|
+
$$getElementBrowseName: (extObject: ExtensionObject, index: number | number[]) => QualifiedName;
|
|
1924
|
+
$$extensionObjectArray: ExtensionObject[];
|
|
1925
|
+
$$indexPropertyName: string;
|
|
1926
|
+
}
|
|
1927
|
+
export interface UAVariableImpl extends UAVariableImplExtArray {
|
|
1928
|
+
}
|
|
1929
|
+
function check_valid_array(dataType: DataType, array: any): boolean {
|
|
1930
|
+
if (Array.isArray(array)) {
|
|
1931
|
+
return true;
|
|
1926
1932
|
}
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
return
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
case DataType.UInt16:
|
|
1945
|
-
return array instanceof Uint16Array;
|
|
1946
|
-
case DataType.Byte:
|
|
1947
|
-
return array instanceof Uint8Array || array instanceof Buffer;
|
|
1948
|
-
}
|
|
1949
|
-
return false;
|
|
1933
|
+
switch (dataType) {
|
|
1934
|
+
case DataType.Double:
|
|
1935
|
+
return array instanceof Float64Array;
|
|
1936
|
+
case DataType.Float:
|
|
1937
|
+
return array instanceof Float32Array;
|
|
1938
|
+
case DataType.Int32:
|
|
1939
|
+
return array instanceof Int32Array;
|
|
1940
|
+
case DataType.Int16:
|
|
1941
|
+
return array instanceof Int16Array;
|
|
1942
|
+
case DataType.SByte:
|
|
1943
|
+
return array instanceof Int8Array;
|
|
1944
|
+
case DataType.UInt32:
|
|
1945
|
+
return array instanceof Uint32Array;
|
|
1946
|
+
case DataType.UInt16:
|
|
1947
|
+
return array instanceof Uint16Array;
|
|
1948
|
+
case DataType.Byte:
|
|
1949
|
+
return array instanceof Uint8Array || array instanceof Buffer;
|
|
1950
1950
|
}
|
|
1951
|
+
return false;
|
|
1952
|
+
}
|
|
1951
1953
|
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
if (!dataValue.sourceTimestamp) {
|
|
1957
|
-
dataValue.sourceTimestamp = now.timestamp;
|
|
1958
|
-
dataValue.sourcePicoseconds = now.picoseconds;
|
|
1959
|
-
}
|
|
1960
|
-
if (!dataValue.serverTimestamp) {
|
|
1961
|
-
dataValue.serverTimestamp = now.timestamp;
|
|
1962
|
-
dataValue.serverPicoseconds = now.picoseconds;
|
|
1963
|
-
}
|
|
1964
|
-
}
|
|
1954
|
+
function _apply_default_timestamps(dataValue: DataValue): void {
|
|
1955
|
+
const now = getCurrentClock();
|
|
1956
|
+
assert(dataValue instanceof DataValue);
|
|
1965
1957
|
|
|
1966
|
-
|
|
1967
|
-
|
|
1958
|
+
if (!dataValue.sourceTimestamp) {
|
|
1959
|
+
dataValue.sourceTimestamp = now.timestamp;
|
|
1960
|
+
dataValue.sourcePicoseconds = now.picoseconds;
|
|
1968
1961
|
}
|
|
1969
|
-
|
|
1970
|
-
|
|
1962
|
+
if (!dataValue.serverTimestamp) {
|
|
1963
|
+
dataValue.serverTimestamp = now.timestamp;
|
|
1964
|
+
dataValue.serverPicoseconds = now.picoseconds;
|
|
1971
1965
|
}
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1966
|
+
}
|
|
1967
|
+
|
|
1968
|
+
function unsetFlag(flags: number, mask: number): number {
|
|
1969
|
+
return flags & ~mask;
|
|
1970
|
+
}
|
|
1971
|
+
function setFlag(flags: number, mask: number): number {
|
|
1972
|
+
return flags | mask;
|
|
1973
|
+
}
|
|
1974
|
+
|
|
1975
|
+
function _calculateEffectiveUserAccessLevelFromPermission(
|
|
1976
|
+
node: UAVariable,
|
|
1977
|
+
context: ISessionContext,
|
|
1978
|
+
userAccessLevel: AccessLevelFlag | undefined
|
|
1979
|
+
): AccessLevelFlag {
|
|
1980
|
+
function __adjustFlag(
|
|
1981
|
+
permissionType: PermissionType,
|
|
1982
|
+
access: AccessLevelFlag,
|
|
1983
|
+
userAccessLevel1: AccessLevelFlag
|
|
1977
1984
|
): AccessLevelFlag {
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
): AccessLevelFlag {
|
|
1983
|
-
if ((node.accessLevel & access) === 0 || (userAccessLevel1 & access) === 0) {
|
|
1985
|
+
if ((node.accessLevel & access) === 0 || (userAccessLevel1 & access) === 0) {
|
|
1986
|
+
userAccessLevel1 = unsetFlag(userAccessLevel1, access);
|
|
1987
|
+
} else {
|
|
1988
|
+
if (!context.checkPermission(node, permissionType)) {
|
|
1984
1989
|
userAccessLevel1 = unsetFlag(userAccessLevel1, access);
|
|
1985
|
-
} else {
|
|
1986
|
-
if (!context.checkPermission(node, permissionType)) {
|
|
1987
|
-
userAccessLevel1 = unsetFlag(userAccessLevel1, access);
|
|
1988
|
-
}
|
|
1989
1990
|
}
|
|
1990
|
-
return userAccessLevel1;
|
|
1991
|
-
}
|
|
1992
|
-
userAccessLevel = node.userAccessLevel === undefined ? node.accessLevel : node.userAccessLevel & node.accessLevel;
|
|
1993
|
-
if (context.checkPermission) {
|
|
1994
|
-
assert(context.checkPermission instanceof Function);
|
|
1995
|
-
userAccessLevel = __adjustFlag(PermissionType.Read, AccessLevelFlag.CurrentRead, userAccessLevel);
|
|
1996
|
-
userAccessLevel = __adjustFlag(PermissionType.Write, AccessLevelFlag.CurrentWrite, userAccessLevel);
|
|
1997
|
-
userAccessLevel = __adjustFlag(PermissionType.Write, AccessLevelFlag.StatusWrite, userAccessLevel);
|
|
1998
|
-
userAccessLevel = __adjustFlag(PermissionType.Write, AccessLevelFlag.TimestampWrite, userAccessLevel);
|
|
1999
|
-
userAccessLevel = __adjustFlag(PermissionType.ReadHistory, AccessLevelFlag.HistoryRead, userAccessLevel);
|
|
2000
|
-
userAccessLevel = __adjustFlag(PermissionType.DeleteHistory, AccessLevelFlag.HistoryWrite, userAccessLevel);
|
|
2001
|
-
return userAccessLevel;
|
|
2002
|
-
} else {
|
|
2003
|
-
return userAccessLevel;
|
|
2004
1991
|
}
|
|
1992
|
+
return userAccessLevel1;
|
|
2005
1993
|
}
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
1994
|
+
userAccessLevel = node.userAccessLevel === undefined ? node.accessLevel : node.userAccessLevel & node.accessLevel;
|
|
1995
|
+
if (context.checkPermission) {
|
|
1996
|
+
assert(context.checkPermission instanceof Function);
|
|
1997
|
+
userAccessLevel = __adjustFlag(PermissionType.Read, AccessLevelFlag.CurrentRead, userAccessLevel);
|
|
1998
|
+
userAccessLevel = __adjustFlag(PermissionType.Write, AccessLevelFlag.CurrentWrite, userAccessLevel);
|
|
1999
|
+
userAccessLevel = __adjustFlag(PermissionType.Write, AccessLevelFlag.StatusWrite, userAccessLevel);
|
|
2000
|
+
userAccessLevel = __adjustFlag(PermissionType.Write, AccessLevelFlag.TimestampWrite, userAccessLevel);
|
|
2001
|
+
userAccessLevel = __adjustFlag(PermissionType.ReadHistory, AccessLevelFlag.HistoryRead, userAccessLevel);
|
|
2002
|
+
userAccessLevel = __adjustFlag(PermissionType.DeleteHistory, AccessLevelFlag.HistoryWrite, userAccessLevel);
|
|
2003
|
+
return userAccessLevel;
|
|
2004
|
+
} else {
|
|
2005
|
+
return userAccessLevel;
|
|
2013
2006
|
}
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2007
|
+
}
|
|
2008
|
+
|
|
2009
|
+
function adjustVariant2(this: UAVariableImpl, variant: Variant): Variant {
|
|
2010
|
+
// convert Variant( Scalar|ByteString) => Variant(Array|ByteArray)
|
|
2011
|
+
const addressSpace = this.addressSpace;
|
|
2012
|
+
const basicType = this.getBasicDataType();
|
|
2013
|
+
variant = adjustVariant(variant, this.valueRank, basicType);
|
|
2014
|
+
return variant;
|
|
2015
|
+
}
|
|
2016
|
+
|
|
2017
|
+
function _not_writable_timestamped_set_func(
|
|
2018
|
+
dataValue: DataValue,
|
|
2019
|
+
callback: (err: Error | null, statusCode: StatusCode, dataValue?: DataValue | null) => void
|
|
2020
|
+
) {
|
|
2021
|
+
assert(dataValue instanceof DataValue);
|
|
2022
|
+
callback(null, StatusCodes.BadNotWritable, null);
|
|
2023
|
+
}
|
|
2024
|
+
|
|
2025
|
+
function _default_writable_timestamped_set_func(
|
|
2026
|
+
dataValue: DataValue,
|
|
2027
|
+
callback: (err: Error | null, statusCode: StatusCode, dataValue?: DataValue | null) => void
|
|
2028
|
+
) {
|
|
2029
|
+
assert(dataValue instanceof DataValue);
|
|
2030
|
+
callback(null, StatusCodes.Good, dataValue);
|
|
2031
|
+
}
|
|
2032
|
+
|
|
2033
|
+
function turn_sync_to_async<T, D, R>(f: (this: T, data: D) => R, numberOfArgs: number) {
|
|
2034
|
+
if (f.length <= numberOfArgs) {
|
|
2035
|
+
return function (this: T, data: D, callback: (err: Error | null, r?: R) => void) {
|
|
2036
|
+
const r = f.call(this, data);
|
|
2037
|
+
setImmediate(() => {
|
|
2038
|
+
return callback(null, r);
|
|
2039
|
+
});
|
|
2040
|
+
};
|
|
2041
|
+
} else {
|
|
2042
|
+
assert(f.length === numberOfArgs + 1);
|
|
2043
|
+
return f;
|
|
2021
2044
|
}
|
|
2045
|
+
}
|
|
2022
2046
|
|
|
2023
|
-
|
|
2024
|
-
dataValue: DataValue,
|
|
2025
|
-
callback: (err: Error | null, statusCode: StatusCode, dataValue?: DataValue | null) => void
|
|
2026
|
-
) {
|
|
2027
|
-
assert(dataValue instanceof DataValue);
|
|
2028
|
-
callback(null, StatusCodes.Good, dataValue);
|
|
2029
|
-
}
|
|
2047
|
+
const _default_minimumSamplingInterval = 1000;
|
|
2030
2048
|
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
const r = f.call(this, data);
|
|
2035
|
-
setImmediate(() => {
|
|
2036
|
-
return callback(null, r);
|
|
2037
|
-
});
|
|
2038
|
-
};
|
|
2039
|
-
} else {
|
|
2040
|
-
assert(f.length === numberOfArgs + 1);
|
|
2041
|
-
return f;
|
|
2042
|
-
}
|
|
2049
|
+
function coerceDataValue(dataValue: DataValue | DataValueLike): DataValue {
|
|
2050
|
+
if (dataValue instanceof DataValue) {
|
|
2051
|
+
return dataValue;
|
|
2043
2052
|
}
|
|
2053
|
+
return new DataValue(dataValue);
|
|
2054
|
+
}
|
|
2044
2055
|
|
|
2045
|
-
|
|
2056
|
+
// variation #3 :
|
|
2057
|
+
function _Variable_bind_with_async_refresh(this: UAVariableImpl, options: any) {
|
|
2058
|
+
/* jshint validthis: true */
|
|
2059
|
+
assert(this instanceof UAVariableImpl);
|
|
2046
2060
|
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
}
|
|
2051
|
-
return new DataValue(dataValue);
|
|
2052
|
-
}
|
|
2061
|
+
assert(typeof options.refreshFunc === "function");
|
|
2062
|
+
assert(!options.get, "a getter shall not be specified when refreshFunc is set");
|
|
2063
|
+
assert(!options.timestamped_get, "a getter shall not be specified when refreshFunc is set");
|
|
2053
2064
|
|
|
2054
|
-
|
|
2055
|
-
function _Variable_bind_with_async_refresh(this: UAVariableImpl, options: any) {
|
|
2056
|
-
/* jshint validthis: true */
|
|
2057
|
-
assert(this instanceof UAVariableImpl);
|
|
2065
|
+
assert(!this.refreshFunc);
|
|
2058
2066
|
|
|
2059
|
-
|
|
2060
|
-
assert(!options.get, "a getter shall not be specified when refreshFunc is set");
|
|
2061
|
-
assert(!options.timestamped_get, "a getter shall not be specified when refreshFunc is set");
|
|
2067
|
+
this.refreshFunc = options.refreshFunc;
|
|
2062
2068
|
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2069
|
+
// TO DO : REVISIT THIS ASSUMPTION
|
|
2070
|
+
if (false && this.minimumSamplingInterval === 0) {
|
|
2071
|
+
// when a getter /timestamped_getter or async_getter is provided
|
|
2072
|
+
// samplingInterval cannot be 0, as the item value must be scanned to be updated.
|
|
2073
|
+
this.minimumSamplingInterval = _default_minimumSamplingInterval; // MonitoredItem.minimumSamplingInterval;
|
|
2074
|
+
debugLog("adapting minimumSamplingInterval on " + this.browseName.toString() + " to " + this.minimumSamplingInterval);
|
|
2075
|
+
}
|
|
2076
|
+
}
|
|
2077
|
+
|
|
2078
|
+
// variation 2
|
|
2079
|
+
function _Variable_bind_with_timestamped_get(
|
|
2080
|
+
this: UAVariableImpl,
|
|
2081
|
+
options: {
|
|
2082
|
+
get: undefined;
|
|
2083
|
+
timestamped_get: TimestampGetFunc;
|
|
2084
|
+
}
|
|
2085
|
+
) {
|
|
2086
|
+
/* jshint validthis: true */
|
|
2087
|
+
assert(this instanceof UAVariableImpl);
|
|
2088
|
+
assert(typeof options.timestamped_get === "function");
|
|
2089
|
+
assert(!options.get, "should not specify 'get' when 'timestamped_get' exists ");
|
|
2090
|
+
assert(!this._timestamped_get_func);
|
|
2091
|
+
|
|
2092
|
+
const async_refresh_func = (callback: (err: Error | null, dataValue?: DataValue) => void) => {
|
|
2093
|
+
Promise.resolve((this._timestamped_get_func! as VariableDataValueGetterSync).call(this))
|
|
2094
|
+
.then((dataValue) => callback(null, dataValue))
|
|
2095
|
+
.catch((err) => {
|
|
2096
|
+
errorLog("asyncRefresh error: Variable is ", this.nodeId.toString(), this.browseName.toString());
|
|
2097
|
+
callback(err as Error);
|
|
2098
|
+
});
|
|
2099
|
+
};
|
|
2100
|
+
const pThis = this as UAVariable;
|
|
2101
|
+
if (options.timestamped_get.length === 0) {
|
|
2102
|
+
const timestamped_get = options.timestamped_get as (this: UAVariable) => DataValue | Promise<DataValue>;
|
|
2103
|
+
// sync version | Promise version
|
|
2104
|
+
this._timestamped_get_func = timestamped_get;
|
|
2105
|
+
|
|
2106
|
+
const dataValue_verify = timestamped_get.call(pThis);
|
|
2107
|
+
// dataValue_verify should be a DataValue or a Promise
|
|
2108
|
+
/* istanbul ignore next */
|
|
2109
|
+
if (!(dataValue_verify instanceof DataValue) && typeof dataValue_verify.then !== "function") {
|
|
2110
|
+
errorLog(
|
|
2111
|
+
chalk.red(" Bind variable error: "),
|
|
2112
|
+
" the timestamped_get function must return a DataValue or a Promise<DataValue>" +
|
|
2113
|
+
"\n value_check.constructor.name ",
|
|
2114
|
+
dataValue_verify ? dataValue_verify.constructor.name : "null"
|
|
2115
|
+
);
|
|
2066
2116
|
|
|
2067
|
-
|
|
2068
|
-
if (false && this.minimumSamplingInterval === 0) {
|
|
2069
|
-
// when a getter /timestamped_getter or async_getter is provided
|
|
2070
|
-
// samplingInterval cannot be 0, as the item value must be scanned to be updated.
|
|
2071
|
-
this.minimumSamplingInterval = _default_minimumSamplingInterval; // MonitoredItem.minimumSamplingInterval;
|
|
2072
|
-
debugLog("adapting minimumSamplingInterval on " + this.browseName.toString() + " to " + this.minimumSamplingInterval);
|
|
2117
|
+
throw new Error(" Bind variable error: " + " the timestamped_get function must return a DataValue");
|
|
2073
2118
|
}
|
|
2119
|
+
_Variable_bind_with_async_refresh.call(this, { refreshFunc: async_refresh_func });
|
|
2120
|
+
} else if (options.timestamped_get.length === 1) {
|
|
2121
|
+
_Variable_bind_with_async_refresh.call(this, { refreshFunc: options.timestamped_get });
|
|
2122
|
+
} else {
|
|
2123
|
+
errorLog("timestamped_get has a invalid number of argument , should be 0 or 1 ");
|
|
2124
|
+
throw new Error("timestamped_get has a invalid number of argument , should be 0 or 1 ");
|
|
2074
2125
|
}
|
|
2126
|
+
}
|
|
2075
2127
|
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
)
|
|
2084
|
-
|
|
2085
|
-
assert(this instanceof UAVariableImpl);
|
|
2086
|
-
assert(typeof options.timestamped_get === "function");
|
|
2087
|
-
assert(!options.get, "should not specify 'get' when 'timestamped_get' exists ");
|
|
2088
|
-
assert(!this._timestamped_get_func);
|
|
2128
|
+
// variation 1
|
|
2129
|
+
function _Variable_bind_with_simple_get(this: UAVariableImpl, options: GetterOptions) {
|
|
2130
|
+
/* jshint validthis: true */
|
|
2131
|
+
assert(this instanceof UAVariableImpl);
|
|
2132
|
+
assert(typeof options.get === "function", "should specify get function");
|
|
2133
|
+
assert(options.get!.length === 0, "get function should not have arguments");
|
|
2134
|
+
assert(!options.timestamped_get, "should not specify a timestamped_get function when get is specified");
|
|
2135
|
+
assert(!this._timestamped_get_func);
|
|
2136
|
+
assert(!this._get_func);
|
|
2089
2137
|
|
|
2090
|
-
|
|
2091
|
-
Promise.resolve((this._timestamped_get_func! as VariableDataValueGetterSync).call(this))
|
|
2092
|
-
.then((dataValue) => callback(null, dataValue))
|
|
2093
|
-
.catch((err) => {
|
|
2094
|
-
errorLog("asyncRefresh error: Variable is ", this.nodeId.toString(), this.browseName.toString());
|
|
2095
|
-
callback(err as Error);
|
|
2096
|
-
});
|
|
2097
|
-
};
|
|
2098
|
-
const pThis = this as UAVariable;
|
|
2099
|
-
if (options.timestamped_get.length === 0) {
|
|
2100
|
-
const timestamped_get = options.timestamped_get as (this: UAVariable) => DataValue | Promise<DataValue>;
|
|
2101
|
-
// sync version | Promise version
|
|
2102
|
-
this._timestamped_get_func = timestamped_get;
|
|
2103
|
-
|
|
2104
|
-
const dataValue_verify = timestamped_get.call(pThis);
|
|
2105
|
-
// dataValue_verify should be a DataValue or a Promise
|
|
2106
|
-
/* istanbul ignore next */
|
|
2107
|
-
if (!(dataValue_verify instanceof DataValue) && typeof dataValue_verify.then !== "function") {
|
|
2108
|
-
errorLog(
|
|
2109
|
-
chalk.red(" Bind variable error: "),
|
|
2110
|
-
" the timestamped_get function must return a DataValue or a Promise<DataValue>" +
|
|
2111
|
-
"\n value_check.constructor.name ",
|
|
2112
|
-
dataValue_verify ? dataValue_verify.constructor.name : "null"
|
|
2113
|
-
);
|
|
2138
|
+
this._get_func = options.get;
|
|
2114
2139
|
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2140
|
+
const timestamped_get_func_from__Variable_bind_with_simple_get = () => {
|
|
2141
|
+
const value: Variant | StatusCode = this._get_func();
|
|
2142
|
+
|
|
2143
|
+
/* istanbul ignore next */
|
|
2144
|
+
if (!is_Variant_or_StatusCode(value)) {
|
|
2145
|
+
errorLog(
|
|
2146
|
+
chalk.red(" Bind variable error: "),
|
|
2147
|
+
" : the getter must return a Variant or a StatusCode" + "\nvalue_check.constructor.name ",
|
|
2148
|
+
value ? value.constructor.name : "null"
|
|
2149
|
+
);
|
|
2150
|
+
throw new Error(
|
|
2151
|
+
" bindVariable : the value getter function returns a invalid result ( expecting a Variant or a StatusCode !!!"
|
|
2152
|
+
);
|
|
2153
|
+
}
|
|
2154
|
+
if (is_StatusCode(value)) {
|
|
2155
|
+
return new DataValue({ statusCode: value as StatusCode });
|
|
2120
2156
|
} else {
|
|
2121
|
-
|
|
2122
|
-
|
|
2157
|
+
if (!this.$dataValue || !this.$dataValue.statusCode.isGoodish() || !sameVariant(this.$dataValue.value, value as Variant)) {
|
|
2158
|
+
this._inner_replace_dataValue(new DataValue({ value }));
|
|
2159
|
+
}
|
|
2160
|
+
return this.$dataValue;
|
|
2123
2161
|
}
|
|
2124
|
-
}
|
|
2162
|
+
};
|
|
2163
|
+
|
|
2164
|
+
_Variable_bind_with_timestamped_get.call(this, {
|
|
2165
|
+
get: undefined,
|
|
2166
|
+
timestamped_get: timestamped_get_func_from__Variable_bind_with_simple_get
|
|
2167
|
+
});
|
|
2168
|
+
}
|
|
2125
2169
|
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
assert(typeof options.get === "function", "should specify get function");
|
|
2131
|
-
assert(options.get!.length === 0, "get function should not have arguments");
|
|
2132
|
-
assert(!options.timestamped_get, "should not specify a timestamped_get function when get is specified");
|
|
2133
|
-
assert(!this._timestamped_get_func);
|
|
2134
|
-
assert(!this._get_func);
|
|
2170
|
+
function _Variable_bind_with_simple_set(this: UAVariableImpl, options: any) {
|
|
2171
|
+
assert(this instanceof UAVariableImpl);
|
|
2172
|
+
assert(typeof options.set === "function", "should specify set function");
|
|
2173
|
+
assert(!options.timestamped_set, "should not specify a timestamped_set function");
|
|
2135
2174
|
|
|
2136
|
-
|
|
2175
|
+
assert(!this._timestamped_set_func);
|
|
2176
|
+
assert(!this._set_func);
|
|
2137
2177
|
|
|
2138
|
-
|
|
2139
|
-
|
|
2178
|
+
this._set_func = turn_sync_to_async(options.set, 1);
|
|
2179
|
+
assert(this._set_func.length === 2, " set function must have 2 arguments ( variant, callback)");
|
|
2140
2180
|
|
|
2141
|
-
|
|
2142
|
-
|
|
2181
|
+
this._timestamped_set_func = (
|
|
2182
|
+
timestamped_value: DataValue,
|
|
2183
|
+
callback: (err: Error | null, statusCode: StatusCode, dataValue: DataValue) => void
|
|
2184
|
+
) => {
|
|
2185
|
+
assert(timestamped_value instanceof DataValue);
|
|
2186
|
+
this._set_func(timestamped_value.value, (err: Error | null, statusCode: StatusCode) => {
|
|
2187
|
+
// istanbul ignore next
|
|
2188
|
+
if (!err && !statusCode) {
|
|
2143
2189
|
errorLog(
|
|
2144
|
-
chalk.red("
|
|
2145
|
-
" : the getter must return a Variant or a StatusCode" + "\nvalue_check.constructor.name ",
|
|
2146
|
-
value ? value.constructor.name : "null"
|
|
2190
|
+
chalk.red("UAVariable Binding Error _set_func must return a StatusCode, check the bindVariable parameters")
|
|
2147
2191
|
);
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
);
|
|
2151
|
-
}
|
|
2152
|
-
if (is_StatusCode(value)) {
|
|
2153
|
-
return new DataValue({ statusCode: value as StatusCode });
|
|
2154
|
-
} else {
|
|
2155
|
-
if (!this.$dataValue || !this.$dataValue.statusCode.isGoodish() || !sameVariant(this.$dataValue.value, value as Variant)) {
|
|
2156
|
-
this._inner_replace_dataValue(new DataValue({ value }));
|
|
2157
|
-
}
|
|
2158
|
-
return this.$dataValue;
|
|
2192
|
+
errorLog(chalk.yellow("StatusCode.Good is assumed"));
|
|
2193
|
+
return callback(err, StatusCodes.Good, timestamped_value);
|
|
2159
2194
|
}
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
_Variable_bind_with_timestamped_get.call(this, {
|
|
2163
|
-
get: undefined,
|
|
2164
|
-
timestamped_get: timestamped_get_func_from__Variable_bind_with_simple_get
|
|
2195
|
+
callback(err, statusCode, timestamped_value);
|
|
2165
2196
|
});
|
|
2197
|
+
};
|
|
2198
|
+
}
|
|
2199
|
+
|
|
2200
|
+
function _Variable_bind_with_timestamped_set(
|
|
2201
|
+
this: UAVariableImpl,
|
|
2202
|
+
options: {
|
|
2203
|
+
timestamped_set: TimestampSetFunc;
|
|
2204
|
+
set: undefined;
|
|
2166
2205
|
}
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2206
|
+
) {
|
|
2207
|
+
assert(
|
|
2208
|
+
options.timestamped_set.length === 2 || options.timestamped_set.length === 1,
|
|
2209
|
+
"timestamped_set must have 2 parameters timestamped_set: function(dataValue,callback){} or one paramater timestamped_set: function(dataValue): Promise<StatusCode>{}"
|
|
2210
|
+
);
|
|
2211
|
+
assert(!options.set, "should not specify set when timestamped_set_func exists ");
|
|
2212
|
+
this._timestamped_set_func = convertToCallbackFunction1<StatusCode, DataValue, UAVariable>(options.timestamped_set);
|
|
2213
|
+
}
|
|
2214
|
+
|
|
2215
|
+
interface SetterOptions {
|
|
2216
|
+
set?: SetFunc;
|
|
2217
|
+
timestamped_set?: TimestampSetFunc;
|
|
2218
|
+
timestamped_get?: TimestampGetFunc;
|
|
2219
|
+
}
|
|
2220
|
+
function bind_setter(this: UAVariableImpl, options: SetterOptions) {
|
|
2221
|
+
if (typeof options.set === "function") {
|
|
2222
|
+
// variation 1
|
|
2223
|
+
_Variable_bind_with_simple_set.call(this, options);
|
|
2224
|
+
} else if (typeof options.timestamped_set === "function") {
|
|
2225
|
+
// variation 2
|
|
2226
|
+
assert(typeof options.timestamped_get === "function", "timestamped_set must be used with timestamped_get ");
|
|
2227
|
+
_Variable_bind_with_timestamped_set.call(this, {
|
|
2228
|
+
set: undefined,
|
|
2229
|
+
timestamped_set: options.timestamped_set
|
|
2230
|
+
});
|
|
2231
|
+
} else if (typeof options.timestamped_get === "function") {
|
|
2232
|
+
// timestamped_get is specified but timestamped_set is not
|
|
2233
|
+
// => Value is read-only
|
|
2234
|
+
_Variable_bind_with_timestamped_set.call(this, {
|
|
2235
|
+
set: undefined,
|
|
2236
|
+
timestamped_set: _not_writable_timestamped_set_func
|
|
2237
|
+
});
|
|
2238
|
+
} else {
|
|
2239
|
+
_Variable_bind_with_timestamped_set.call(this, {
|
|
2240
|
+
set: undefined,
|
|
2241
|
+
timestamped_set: _default_writable_timestamped_set_func
|
|
2242
|
+
});
|
|
2196
2243
|
}
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2244
|
+
}
|
|
2245
|
+
|
|
2246
|
+
interface GetterOptions {
|
|
2247
|
+
get?: GetFunc;
|
|
2248
|
+
timestamped_get?: TimestampGetFunc;
|
|
2249
|
+
refreshFunc?: (callback: CallbackT<DataValue>) => void;
|
|
2250
|
+
dataType?: DataType | string;
|
|
2251
|
+
value?: any;
|
|
2252
|
+
}
|
|
2253
|
+
function bind_getter(this: UAVariableImpl, options: GetterOptions) {
|
|
2254
|
+
if (typeof options.get === "function") {
|
|
2255
|
+
// variation 1
|
|
2256
|
+
_Variable_bind_with_simple_get.call(this, options);
|
|
2257
|
+
} else if (typeof options.timestamped_get === "function") {
|
|
2258
|
+
// variation 2
|
|
2259
|
+
_Variable_bind_with_timestamped_get.call(this, {
|
|
2260
|
+
get: undefined,
|
|
2261
|
+
timestamped_get: options.timestamped_get
|
|
2262
|
+
});
|
|
2263
|
+
} else if (typeof options.refreshFunc === "function") {
|
|
2264
|
+
// variation 3
|
|
2265
|
+
_Variable_bind_with_async_refresh.call(this, options);
|
|
2266
|
+
} else {
|
|
2205
2267
|
assert(
|
|
2206
|
-
|
|
2207
|
-
"
|
|
2268
|
+
!Object.prototype.hasOwnProperty.call(options, "set"),
|
|
2269
|
+
"getter is missing : a getter must be provided if a setter is provided"
|
|
2208
2270
|
);
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
set?: SetFunc;
|
|
2215
|
-
timestamped_set?: TimestampSetFunc;
|
|
2216
|
-
timestamped_get?: TimestampGetFunc;
|
|
2217
|
-
}
|
|
2218
|
-
function bind_setter(this: UAVariableImpl, options: SetterOptions) {
|
|
2219
|
-
if (typeof options.set === "function") {
|
|
2220
|
-
// variation 1
|
|
2221
|
-
_Variable_bind_with_simple_set.call(this, options);
|
|
2222
|
-
} else if (typeof options.timestamped_set === "function") {
|
|
2223
|
-
// variation 2
|
|
2224
|
-
assert(typeof options.timestamped_get === "function", "timestamped_set must be used with timestamped_get ");
|
|
2225
|
-
_Variable_bind_with_timestamped_set.call(this, {
|
|
2226
|
-
set: undefined,
|
|
2227
|
-
timestamped_set: options.timestamped_set
|
|
2228
|
-
});
|
|
2229
|
-
} else if (typeof options.timestamped_get === "function") {
|
|
2230
|
-
// timestamped_get is specified but timestamped_set is not
|
|
2231
|
-
// => Value is read-only
|
|
2232
|
-
_Variable_bind_with_timestamped_set.call(this, {
|
|
2233
|
-
set: undefined,
|
|
2234
|
-
timestamped_set: _not_writable_timestamped_set_func
|
|
2235
|
-
});
|
|
2236
|
-
} else {
|
|
2237
|
-
_Variable_bind_with_timestamped_set.call(this, {
|
|
2238
|
-
set: undefined,
|
|
2239
|
-
timestamped_set: _default_writable_timestamped_set_func
|
|
2240
|
-
});
|
|
2271
|
+
// xx bind_variant.call(this,options);
|
|
2272
|
+
if (options.dataType !== undefined) {
|
|
2273
|
+
// if (options.dataType !== DataType.ExtensionObject) {
|
|
2274
|
+
this.setValueFromSource(options as VariantLike);
|
|
2275
|
+
// }
|
|
2241
2276
|
}
|
|
2242
2277
|
}
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
// }
|
|
2274
|
-
}
|
|
2275
|
-
}
|
|
2276
|
-
}
|
|
2277
|
-
|
|
2278
|
-
export interface UAVariableImplT<T, DT extends DataType> extends UAVariableImpl, UAVariableT<T, DT> {
|
|
2279
|
-
on(): any;
|
|
2280
|
-
once(): any;
|
|
2281
|
-
readValueAsync(context: ISessionContext | null): Promise<DataValueT<T, DT>>;
|
|
2282
|
-
readValueAsync(context: ISessionContext | null, callback: CallbackT<DataValueT<T, DT>>): void;
|
|
2283
|
-
|
|
2284
|
-
readValue(
|
|
2285
|
-
context?: ISessionContext | null,
|
|
2286
|
-
indexRange?: NumericRange,
|
|
2287
|
-
dataEncoding?: QualifiedNameLike | null
|
|
2288
|
-
): DataValueT<T, DT>;
|
|
2289
|
-
|
|
2290
|
-
readValue(
|
|
2291
|
-
context?: ISessionContext | null,
|
|
2292
|
-
indexRange?: NumericRange,
|
|
2293
|
-
dataEncoding?: QualifiedNameLike | null
|
|
2294
|
-
): DataValueT<T, DT>;
|
|
2295
|
-
|
|
2296
|
-
writeValue(
|
|
2297
|
-
context: ISessionContext,
|
|
2298
|
-
dataValue: DataValueT<T, DT>,
|
|
2299
|
-
indexRange: NumericRange | null,
|
|
2300
|
-
callback: StatusCodeCallback
|
|
2301
|
-
): void;
|
|
2302
|
-
writeValue(context: ISessionContext, dataValue: DataValueT<T, DT>, callback: StatusCodeCallback): void;
|
|
2303
|
-
writeValue(context: ISessionContext, dataValue: DataValueT<T, DT>, indexRange?: NumericRange | null): Promise<StatusCode>;
|
|
2304
|
-
}
|
|
2305
|
-
export class UAVariableImplT<T, DT extends DataType> extends UAVariableImpl { }
|
|
2278
|
+
}
|
|
2279
|
+
|
|
2280
|
+
export interface UAVariableImplT<T, DT extends DataType> extends UAVariableImpl, UAVariableT<T, DT> {
|
|
2281
|
+
on(): any;
|
|
2282
|
+
once(): any;
|
|
2283
|
+
readValueAsync(context: ISessionContext | null): Promise<DataValueT<T, DT>>;
|
|
2284
|
+
readValueAsync(context: ISessionContext | null, callback: CallbackT<DataValueT<T, DT>>): void;
|
|
2285
|
+
|
|
2286
|
+
readValue(
|
|
2287
|
+
context?: ISessionContext | null,
|
|
2288
|
+
indexRange?: NumericRange,
|
|
2289
|
+
dataEncoding?: QualifiedNameLike | null
|
|
2290
|
+
): DataValueT<T, DT>;
|
|
2291
|
+
|
|
2292
|
+
readValue(
|
|
2293
|
+
context?: ISessionContext | null,
|
|
2294
|
+
indexRange?: NumericRange,
|
|
2295
|
+
dataEncoding?: QualifiedNameLike | null
|
|
2296
|
+
): DataValueT<T, DT>;
|
|
2297
|
+
|
|
2298
|
+
writeValue(
|
|
2299
|
+
context: ISessionContext,
|
|
2300
|
+
dataValue: DataValueT<T, DT>,
|
|
2301
|
+
indexRange: NumericRange | null,
|
|
2302
|
+
callback: StatusCodeCallback
|
|
2303
|
+
): void;
|
|
2304
|
+
writeValue(context: ISessionContext, dataValue: DataValueT<T, DT>, callback: StatusCodeCallback): void;
|
|
2305
|
+
writeValue(context: ISessionContext, dataValue: DataValueT<T, DT>, indexRange?: NumericRange | null): Promise<StatusCode>;
|
|
2306
|
+
}
|
|
2307
|
+
export class UAVariableImplT<T, DT extends DataType> extends UAVariableImpl { }
|