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.
Files changed (433) hide show
  1. package/package.json +37 -37
  2. package/source/interfaces/alarms_and_conditions/ua_condition_ex.ts +4 -3
  3. package/source/loader/make_xml_extension_object_parser.ts +10 -9
  4. package/src/address_space.ts +6 -5
  5. package/src/alarms_and_conditions/ua_condition_impl.ts +14 -9
  6. package/src/base_node_impl.ts +6 -2
  7. package/src/base_node_private.ts +73 -28
  8. package/src/data_access/ua_two_state_discrete_impl.ts +2 -0
  9. package/src/ua_variable_impl.ts +2039 -2037
  10. package/src/ua_variable_type_impl.ts +35 -17
  11. package/dist/source/address_space_ts.d.ts +0 -118
  12. package/dist/source/address_space_ts.js +0 -18
  13. package/dist/source/address_space_ts.js.map +0 -1
  14. package/dist/source/continuation_points/continuation_point_manager.d.ts +0 -91
  15. package/dist/source/continuation_points/continuation_point_manager.js +0 -201
  16. package/dist/source/continuation_points/continuation_point_manager.js.map +0 -1
  17. package/dist/source/helpers/adjust_browse_direction.d.ts +0 -5
  18. package/dist/source/helpers/adjust_browse_direction.js +0 -12
  19. package/dist/source/helpers/adjust_browse_direction.js.map +0 -1
  20. package/dist/source/helpers/argument_list.d.ts +0 -33
  21. package/dist/source/helpers/argument_list.js +0 -255
  22. package/dist/source/helpers/argument_list.js.map +0 -1
  23. package/dist/source/helpers/call_helpers.d.ts +0 -6
  24. package/dist/source/helpers/call_helpers.js +0 -72
  25. package/dist/source/helpers/call_helpers.js.map +0 -1
  26. package/dist/source/helpers/coerce_enum_value.d.ts +0 -6
  27. package/dist/source/helpers/coerce_enum_value.js +0 -34
  28. package/dist/source/helpers/coerce_enum_value.js.map +0 -1
  29. package/dist/source/helpers/dump_tools.d.ts +0 -14
  30. package/dist/source/helpers/dump_tools.js +0 -79
  31. package/dist/source/helpers/dump_tools.js.map +0 -1
  32. package/dist/source/helpers/ensure_secure_access.d.ts +0 -9
  33. package/dist/source/helpers/ensure_secure_access.js +0 -77
  34. package/dist/source/helpers/ensure_secure_access.js.map +0 -1
  35. package/dist/source/helpers/make_optionals_map.d.ts +0 -21
  36. package/dist/source/helpers/make_optionals_map.js +0 -30
  37. package/dist/source/helpers/make_optionals_map.js.map +0 -1
  38. package/dist/source/helpers/multiform_func.d.ts +0 -11
  39. package/dist/source/helpers/multiform_func.js +0 -76
  40. package/dist/source/helpers/multiform_func.js.map +0 -1
  41. package/dist/source/helpers/resolve_opaque_on_address_space.d.ts +0 -3
  42. package/dist/source/helpers/resolve_opaque_on_address_space.js +0 -37
  43. package/dist/source/helpers/resolve_opaque_on_address_space.js.map +0 -1
  44. package/dist/source/index.d.ts +0 -61
  45. package/dist/source/index.js +0 -90
  46. package/dist/source/index.js.map +0 -1
  47. package/dist/source/interfaces/alarms_and_conditions/condition_info_i.d.ts +0 -19
  48. package/dist/source/interfaces/alarms_and_conditions/condition_info_i.js +0 -3
  49. package/dist/source/interfaces/alarms_and_conditions/condition_info_i.js.map +0 -1
  50. package/dist/source/interfaces/alarms_and_conditions/condition_snapshot.d.ts +0 -193
  51. package/dist/source/interfaces/alarms_and_conditions/condition_snapshot.js +0 -3
  52. package/dist/source/interfaces/alarms_and_conditions/condition_snapshot.js.map +0 -1
  53. package/dist/source/interfaces/alarms_and_conditions/deviation_stuff.d.ts +0 -12
  54. package/dist/source/interfaces/alarms_and_conditions/deviation_stuff.js +0 -3
  55. package/dist/source/interfaces/alarms_and_conditions/deviation_stuff.js.map +0 -1
  56. package/dist/source/interfaces/alarms_and_conditions/install_setpoint_options.d.ts +0 -10
  57. package/dist/source/interfaces/alarms_and_conditions/install_setpoint_options.js +0 -3
  58. package/dist/source/interfaces/alarms_and_conditions/install_setpoint_options.js.map +0 -1
  59. package/dist/source/interfaces/alarms_and_conditions/instantiate_alarm_condition_options.d.ts +0 -7
  60. package/dist/source/interfaces/alarms_and_conditions/instantiate_alarm_condition_options.js +0 -3
  61. package/dist/source/interfaces/alarms_and_conditions/instantiate_alarm_condition_options.js.map +0 -1
  62. package/dist/source/interfaces/alarms_and_conditions/instantiate_condition_options.d.ts +0 -7
  63. package/dist/source/interfaces/alarms_and_conditions/instantiate_condition_options.js +0 -3
  64. package/dist/source/interfaces/alarms_and_conditions/instantiate_condition_options.js.map +0 -1
  65. package/dist/source/interfaces/alarms_and_conditions/instantiate_exclusive_deviation_alarm_options.d.ts +0 -4
  66. package/dist/source/interfaces/alarms_and_conditions/instantiate_exclusive_deviation_alarm_options.js +0 -3
  67. package/dist/source/interfaces/alarms_and_conditions/instantiate_exclusive_deviation_alarm_options.js.map +0 -1
  68. package/dist/source/interfaces/alarms_and_conditions/instantiate_exclusive_limit_alarm_options.d.ts +0 -4
  69. package/dist/source/interfaces/alarms_and_conditions/instantiate_exclusive_limit_alarm_options.js +0 -3
  70. package/dist/source/interfaces/alarms_and_conditions/instantiate_exclusive_limit_alarm_options.js.map +0 -1
  71. package/dist/source/interfaces/alarms_and_conditions/instantiate_limit_alarm_options.d.ts +0 -9
  72. package/dist/source/interfaces/alarms_and_conditions/instantiate_limit_alarm_options.js +0 -3
  73. package/dist/source/interfaces/alarms_and_conditions/instantiate_limit_alarm_options.js.map +0 -1
  74. package/dist/source/interfaces/alarms_and_conditions/instantiate_non_exclusive_deviation_alarm_options.d.ts +0 -4
  75. package/dist/source/interfaces/alarms_and_conditions/instantiate_non_exclusive_deviation_alarm_options.js +0 -3
  76. package/dist/source/interfaces/alarms_and_conditions/instantiate_non_exclusive_deviation_alarm_options.js.map +0 -1
  77. package/dist/source/interfaces/alarms_and_conditions/instantiate_non_exclusive_limit_alarm_options.d.ts +0 -4
  78. package/dist/source/interfaces/alarms_and_conditions/instantiate_non_exclusive_limit_alarm_options.js +0 -3
  79. package/dist/source/interfaces/alarms_and_conditions/instantiate_non_exclusive_limit_alarm_options.js.map +0 -1
  80. package/dist/source/interfaces/alarms_and_conditions/instantiate_off_normal_alarm_options.d.ts +0 -20
  81. package/dist/source/interfaces/alarms_and_conditions/instantiate_off_normal_alarm_options.js +0 -3
  82. package/dist/source/interfaces/alarms_and_conditions/instantiate_off_normal_alarm_options.js.map +0 -1
  83. package/dist/source/interfaces/alarms_and_conditions/ua_acknowledgeable_condition_ex.d.ts +0 -23
  84. package/dist/source/interfaces/alarms_and_conditions/ua_acknowledgeable_condition_ex.js +0 -3
  85. package/dist/source/interfaces/alarms_and_conditions/ua_acknowledgeable_condition_ex.js.map +0 -1
  86. package/dist/source/interfaces/alarms_and_conditions/ua_alarm_condition_ex.d.ts +0 -32
  87. package/dist/source/interfaces/alarms_and_conditions/ua_alarm_condition_ex.js +0 -3
  88. package/dist/source/interfaces/alarms_and_conditions/ua_alarm_condition_ex.js.map +0 -1
  89. package/dist/source/interfaces/alarms_and_conditions/ua_certificate_expiration_alarm_ex.d.ts +0 -19
  90. package/dist/source/interfaces/alarms_and_conditions/ua_certificate_expiration_alarm_ex.js +0 -3
  91. package/dist/source/interfaces/alarms_and_conditions/ua_certificate_expiration_alarm_ex.js.map +0 -1
  92. package/dist/source/interfaces/alarms_and_conditions/ua_condition_ex.d.ts +0 -42
  93. package/dist/source/interfaces/alarms_and_conditions/ua_condition_ex.js +0 -3
  94. package/dist/source/interfaces/alarms_and_conditions/ua_condition_ex.js.map +0 -1
  95. package/dist/source/interfaces/alarms_and_conditions/ua_discrete_alarm_ex.d.ts +0 -7
  96. package/dist/source/interfaces/alarms_and_conditions/ua_discrete_alarm_ex.js +0 -26
  97. package/dist/source/interfaces/alarms_and_conditions/ua_discrete_alarm_ex.js.map +0 -1
  98. package/dist/source/interfaces/alarms_and_conditions/ua_exclusive_deviation_alarm_ex.d.ts +0 -5
  99. package/dist/source/interfaces/alarms_and_conditions/ua_exclusive_deviation_alarm_ex.js +0 -3
  100. package/dist/source/interfaces/alarms_and_conditions/ua_exclusive_deviation_alarm_ex.js.map +0 -1
  101. package/dist/source/interfaces/alarms_and_conditions/ua_exclusive_limit_alarm_ex.d.ts +0 -20
  102. package/dist/source/interfaces/alarms_and_conditions/ua_exclusive_limit_alarm_ex.js +0 -3
  103. package/dist/source/interfaces/alarms_and_conditions/ua_exclusive_limit_alarm_ex.js.map +0 -1
  104. package/dist/source/interfaces/alarms_and_conditions/ua_limit_alarm_ex.d.ts +0 -26
  105. package/dist/source/interfaces/alarms_and_conditions/ua_limit_alarm_ex.js +0 -3
  106. package/dist/source/interfaces/alarms_and_conditions/ua_limit_alarm_ex.js.map +0 -1
  107. package/dist/source/interfaces/alarms_and_conditions/ua_non_exclusive_deviation_alarm_ex.d.ts +0 -8
  108. package/dist/source/interfaces/alarms_and_conditions/ua_non_exclusive_deviation_alarm_ex.js +0 -3
  109. package/dist/source/interfaces/alarms_and_conditions/ua_non_exclusive_deviation_alarm_ex.js.map +0 -1
  110. package/dist/source/interfaces/alarms_and_conditions/ua_non_exclusive_limit_alarm_ex.d.ts +0 -10
  111. package/dist/source/interfaces/alarms_and_conditions/ua_non_exclusive_limit_alarm_ex.js +0 -3
  112. package/dist/source/interfaces/alarms_and_conditions/ua_non_exclusive_limit_alarm_ex.js.map +0 -1
  113. package/dist/source/interfaces/data_access/ua_multistate_discrete_ex.d.ts +0 -21
  114. package/dist/source/interfaces/data_access/ua_multistate_discrete_ex.js +0 -3
  115. package/dist/source/interfaces/data_access/ua_multistate_discrete_ex.js.map +0 -1
  116. package/dist/source/interfaces/data_access/ua_multistate_value_discrete_ex.d.ts +0 -24
  117. package/dist/source/interfaces/data_access/ua_multistate_value_discrete_ex.js +0 -3
  118. package/dist/source/interfaces/data_access/ua_multistate_value_discrete_ex.js.map +0 -1
  119. package/dist/source/interfaces/data_access/ua_two_state_discrete_ex.d.ts +0 -12
  120. package/dist/source/interfaces/data_access/ua_two_state_discrete_ex.js +0 -3
  121. package/dist/source/interfaces/data_access/ua_two_state_discrete_ex.js.map +0 -1
  122. package/dist/source/interfaces/data_access/ua_y_array_item_ex.d.ts +0 -8
  123. package/dist/source/interfaces/data_access/ua_y_array_item_ex.js +0 -3
  124. package/dist/source/interfaces/data_access/ua_y_array_item_ex.js.map +0 -1
  125. package/dist/source/interfaces/extension_object_constructor.d.ts +0 -10
  126. package/dist/source/interfaces/extension_object_constructor.js +0 -3
  127. package/dist/source/interfaces/extension_object_constructor.js.map +0 -1
  128. package/dist/source/interfaces/nodeset_loader_options.d.ts +0 -4
  129. package/dist/source/interfaces/nodeset_loader_options.js +0 -3
  130. package/dist/source/interfaces/nodeset_loader_options.js.map +0 -1
  131. package/dist/source/interfaces/state_machine/ua_exclusive_limit_state_machine_type_ex.d.ts +0 -12
  132. package/dist/source/interfaces/state_machine/ua_exclusive_limit_state_machine_type_ex.js +0 -3
  133. package/dist/source/interfaces/state_machine/ua_exclusive_limit_state_machine_type_ex.js.map +0 -1
  134. package/dist/source/interfaces/state_machine/ua_finite_state_machine_type.d.ts +0 -49
  135. package/dist/source/interfaces/state_machine/ua_finite_state_machine_type.js +0 -3
  136. package/dist/source/interfaces/state_machine/ua_finite_state_machine_type.js.map +0 -1
  137. package/dist/source/interfaces/state_machine/ua_program_state_machine_type.d.ts +0 -11
  138. package/dist/source/interfaces/state_machine/ua_program_state_machine_type.js +0 -3
  139. package/dist/source/interfaces/state_machine/ua_program_state_machine_type.js.map +0 -1
  140. package/dist/source/interfaces/state_machine/ua_shelved_state_machine_ex.d.ts +0 -30
  141. package/dist/source/interfaces/state_machine/ua_shelved_state_machine_ex.js +0 -3
  142. package/dist/source/interfaces/state_machine/ua_shelved_state_machine_ex.js.map +0 -1
  143. package/dist/source/interfaces/state_machine/ua_state_machine_type.d.ts +0 -234
  144. package/dist/source/interfaces/state_machine/ua_state_machine_type.js +0 -3
  145. package/dist/source/interfaces/state_machine/ua_state_machine_type.js.map +0 -1
  146. package/dist/source/interfaces/state_machine/ua_transition_ex.d.ts +0 -6
  147. package/dist/source/interfaces/state_machine/ua_transition_ex.js +0 -3
  148. package/dist/source/interfaces/state_machine/ua_transition_ex.js.map +0 -1
  149. package/dist/source/interfaces/ua_subscription_diagnostics_variable_ex.d.ts +0 -8
  150. package/dist/source/interfaces/ua_subscription_diagnostics_variable_ex.js +0 -3
  151. package/dist/source/interfaces/ua_subscription_diagnostics_variable_ex.js.map +0 -1
  152. package/dist/source/loader/decode_xml_extension_object.d.ts +0 -6
  153. package/dist/source/loader/decode_xml_extension_object.js +0 -72
  154. package/dist/source/loader/decode_xml_extension_object.js.map +0 -1
  155. package/dist/source/loader/ensure_datatype_extracted.d.ts +0 -5
  156. package/dist/source/loader/ensure_datatype_extracted.js +0 -71
  157. package/dist/source/loader/ensure_datatype_extracted.js.map +0 -1
  158. package/dist/source/loader/generateAddressSpaceRaw.d.ts +0 -11
  159. package/dist/source/loader/generateAddressSpaceRaw.js +0 -46
  160. package/dist/source/loader/generateAddressSpaceRaw.js.map +0 -1
  161. package/dist/source/loader/load_nodeset2.d.ts +0 -17
  162. package/dist/source/loader/load_nodeset2.js +0 -1484
  163. package/dist/source/loader/load_nodeset2.js.map +0 -1
  164. package/dist/source/loader/make_semver_compatible.d.ts +0 -6
  165. package/dist/source/loader/make_semver_compatible.js +0 -26
  166. package/dist/source/loader/make_semver_compatible.js.map +0 -1
  167. package/dist/source/loader/make_xml_extension_object_parser.d.ts +0 -28
  168. package/dist/source/loader/make_xml_extension_object_parser.js +0 -326
  169. package/dist/source/loader/make_xml_extension_object_parser.js.map +0 -1
  170. package/dist/source/loader/namespace_post_step.d.ts +0 -10
  171. package/dist/source/loader/namespace_post_step.js +0 -62
  172. package/dist/source/loader/namespace_post_step.js.map +0 -1
  173. package/dist/source/loader/register_node_promoter.d.ts +0 -2
  174. package/dist/source/loader/register_node_promoter.js +0 -10
  175. package/dist/source/loader/register_node_promoter.js.map +0 -1
  176. package/dist/source/namespace.d.ts +0 -6
  177. package/dist/source/namespace.js +0 -3
  178. package/dist/source/namespace.js.map +0 -1
  179. package/dist/source/namespace_alarm_and_condition.d.ts +0 -32
  180. package/dist/source/namespace_alarm_and_condition.js +0 -3
  181. package/dist/source/namespace_alarm_and_condition.js.map +0 -1
  182. package/dist/source/namespace_data_access.d.ts +0 -42
  183. package/dist/source/namespace_data_access.js +0 -3
  184. package/dist/source/namespace_data_access.js.map +0 -1
  185. package/dist/source/namespace_machine_state.d.ts +0 -8
  186. package/dist/source/namespace_machine_state.js +0 -3
  187. package/dist/source/namespace_machine_state.js.map +0 -1
  188. package/dist/source/pseudo_session.d.ts +0 -72
  189. package/dist/source/pseudo_session.js +0 -255
  190. package/dist/source/pseudo_session.js.map +0 -1
  191. package/dist/source/session_context.d.ts +0 -111
  192. package/dist/source/session_context.js +0 -265
  193. package/dist/source/session_context.js.map +0 -1
  194. package/dist/source/set_namespace_meta_data.d.ts +0 -2
  195. package/dist/source/set_namespace_meta_data.js +0 -60
  196. package/dist/source/set_namespace_meta_data.js.map +0 -1
  197. package/dist/source/ua_root_folder.d.ts +0 -9
  198. package/dist/source/ua_root_folder.js +0 -3
  199. package/dist/source/ua_root_folder.js.map +0 -1
  200. package/dist/source/ua_two_state_variable_ex.d.ts +0 -23
  201. package/dist/source/ua_two_state_variable_ex.js +0 -3
  202. package/dist/source/ua_two_state_variable_ex.js.map +0 -1
  203. package/dist/source/xml_writer.d.ts +0 -18
  204. package/dist/source/xml_writer.js +0 -3
  205. package/dist/source/xml_writer.js.map +0 -1
  206. package/dist/src/address_space.d.ts +0 -387
  207. package/dist/src/address_space.js +0 -1385
  208. package/dist/src/address_space.js.map +0 -1
  209. package/dist/src/address_space_change_event_tools.d.ts +0 -6
  210. package/dist/src/address_space_change_event_tools.js +0 -153
  211. package/dist/src/address_space_change_event_tools.js.map +0 -1
  212. package/dist/src/address_space_private.d.ts +0 -43
  213. package/dist/src/address_space_private.js +0 -3
  214. package/dist/src/address_space_private.js.map +0 -1
  215. package/dist/src/alarms_and_conditions/condition.d.ts +0 -5
  216. package/dist/src/alarms_and_conditions/condition.js +0 -79
  217. package/dist/src/alarms_and_conditions/condition.js.map +0 -1
  218. package/dist/src/alarms_and_conditions/condition_info_impl.d.ts +0 -26
  219. package/dist/src/alarms_and_conditions/condition_info_impl.js +0 -55
  220. package/dist/src/alarms_and_conditions/condition_info_impl.js.map +0 -1
  221. package/dist/src/alarms_and_conditions/condition_snapshot_impl.d.ts +0 -222
  222. package/dist/src/alarms_and_conditions/condition_snapshot_impl.js +0 -658
  223. package/dist/src/alarms_and_conditions/condition_snapshot_impl.js.map +0 -1
  224. package/dist/src/alarms_and_conditions/deviation_alarm_helper.d.ts +0 -9
  225. package/dist/src/alarms_and_conditions/deviation_alarm_helper.js +0 -61
  226. package/dist/src/alarms_and_conditions/deviation_alarm_helper.js.map +0 -1
  227. package/dist/src/alarms_and_conditions/index.d.ts +0 -16
  228. package/dist/src/alarms_and_conditions/index.js +0 -33
  229. package/dist/src/alarms_and_conditions/index.js.map +0 -1
  230. package/dist/src/alarms_and_conditions/ua_acknowledgeable_condition_impl.d.ts +0 -44
  231. package/dist/src/alarms_and_conditions/ua_acknowledgeable_condition_impl.js +0 -245
  232. package/dist/src/alarms_and_conditions/ua_acknowledgeable_condition_impl.js.map +0 -1
  233. package/dist/src/alarms_and_conditions/ua_alarm_condition_impl.d.ts +0 -93
  234. package/dist/src/alarms_and_conditions/ua_alarm_condition_impl.js +0 -419
  235. package/dist/src/alarms_and_conditions/ua_alarm_condition_impl.js.map +0 -1
  236. package/dist/src/alarms_and_conditions/ua_base_event_impl.d.ts +0 -26
  237. package/dist/src/alarms_and_conditions/ua_base_event_impl.js +0 -39
  238. package/dist/src/alarms_and_conditions/ua_base_event_impl.js.map +0 -1
  239. package/dist/src/alarms_and_conditions/ua_certificate_expiration_alarm_impl.d.ts +0 -44
  240. package/dist/src/alarms_and_conditions/ua_certificate_expiration_alarm_impl.js +0 -184
  241. package/dist/src/alarms_and_conditions/ua_certificate_expiration_alarm_impl.js.map +0 -1
  242. package/dist/src/alarms_and_conditions/ua_condition_impl.d.ts +0 -153
  243. package/dist/src/alarms_and_conditions/ua_condition_impl.js +0 -1029
  244. package/dist/src/alarms_and_conditions/ua_condition_impl.js.map +0 -1
  245. package/dist/src/alarms_and_conditions/ua_discrete_alarm_impl.d.ts +0 -14
  246. package/dist/src/alarms_and_conditions/ua_discrete_alarm_impl.js +0 -35
  247. package/dist/src/alarms_and_conditions/ua_discrete_alarm_impl.js.map +0 -1
  248. package/dist/src/alarms_and_conditions/ua_exclusive_deviation_alarm_impl.d.ts +0 -24
  249. package/dist/src/alarms_and_conditions/ua_exclusive_deviation_alarm_impl.js +0 -57
  250. package/dist/src/alarms_and_conditions/ua_exclusive_deviation_alarm_impl.js.map +0 -1
  251. package/dist/src/alarms_and_conditions/ua_exclusive_level_alarm_impl.d.ts +0 -11
  252. package/dist/src/alarms_and_conditions/ua_exclusive_level_alarm_impl.js +0 -12
  253. package/dist/src/alarms_and_conditions/ua_exclusive_level_alarm_impl.js.map +0 -1
  254. package/dist/src/alarms_and_conditions/ua_exclusive_limit_alarm_impl.d.ts +0 -23
  255. package/dist/src/alarms_and_conditions/ua_exclusive_limit_alarm_impl.js +0 -87
  256. package/dist/src/alarms_and_conditions/ua_exclusive_limit_alarm_impl.js.map +0 -1
  257. package/dist/src/alarms_and_conditions/ua_exclusive_rate_of_change_alarm_impl.d.ts +0 -11
  258. package/dist/src/alarms_and_conditions/ua_exclusive_rate_of_change_alarm_impl.js +0 -8
  259. package/dist/src/alarms_and_conditions/ua_exclusive_rate_of_change_alarm_impl.js.map +0 -1
  260. package/dist/src/alarms_and_conditions/ua_limit_alarm_impl.d.ts +0 -79
  261. package/dist/src/alarms_and_conditions/ua_limit_alarm_impl.js +0 -251
  262. package/dist/src/alarms_and_conditions/ua_limit_alarm_impl.js.map +0 -1
  263. package/dist/src/alarms_and_conditions/ua_non_exclusive_deviation_alarm_impl.d.ts +0 -24
  264. package/dist/src/alarms_and_conditions/ua_non_exclusive_deviation_alarm_impl.js +0 -51
  265. package/dist/src/alarms_and_conditions/ua_non_exclusive_deviation_alarm_impl.js.map +0 -1
  266. package/dist/src/alarms_and_conditions/ua_non_exclusive_limit_alarm_impl.d.ts +0 -19
  267. package/dist/src/alarms_and_conditions/ua_non_exclusive_limit_alarm_impl.js +0 -163
  268. package/dist/src/alarms_and_conditions/ua_non_exclusive_limit_alarm_impl.js.map +0 -1
  269. package/dist/src/alarms_and_conditions/ua_off_normal_alarm_impl.d.ts +0 -46
  270. package/dist/src/alarms_and_conditions/ua_off_normal_alarm_impl.js +0 -166
  271. package/dist/src/alarms_and_conditions/ua_off_normal_alarm_impl.js.map +0 -1
  272. package/dist/src/alarms_and_conditions/ua_system_off_normal_alarm_impl.d.ts +0 -18
  273. package/dist/src/alarms_and_conditions/ua_system_off_normal_alarm_impl.js +0 -18
  274. package/dist/src/alarms_and_conditions/ua_system_off_normal_alarm_impl.js.map +0 -1
  275. package/dist/src/apply_condition_refresh.d.ts +0 -6
  276. package/dist/src/apply_condition_refresh.js +0 -28
  277. package/dist/src/apply_condition_refresh.js.map +0 -1
  278. package/dist/src/base_node_impl.d.ts +0 -283
  279. package/dist/src/base_node_impl.js +0 -1452
  280. package/dist/src/base_node_impl.js.map +0 -1
  281. package/dist/src/base_node_private.d.ts +0 -81
  282. package/dist/src/base_node_private.js +0 -804
  283. package/dist/src/base_node_private.js.map +0 -1
  284. package/dist/src/check_value_rank_compatibility.d.ts +0 -15
  285. package/dist/src/check_value_rank_compatibility.js +0 -82
  286. package/dist/src/check_value_rank_compatibility.js.map +0 -1
  287. package/dist/src/data_access/add_dataItem_stuff.d.ts +0 -11
  288. package/dist/src/data_access/add_dataItem_stuff.js +0 -62
  289. package/dist/src/data_access/add_dataItem_stuff.js.map +0 -1
  290. package/dist/src/data_access/check_variant_compatibility_ua_analog_item.d.ts +0 -1
  291. package/dist/src/data_access/check_variant_compatibility_ua_analog_item.js +0 -35
  292. package/dist/src/data_access/check_variant_compatibility_ua_analog_item.js.map +0 -1
  293. package/dist/src/data_access/ua_multistate_discrete_impl.d.ts +0 -32
  294. package/dist/src/data_access/ua_multistate_discrete_impl.js +0 -131
  295. package/dist/src/data_access/ua_multistate_discrete_impl.js.map +0 -1
  296. package/dist/src/data_access/ua_multistate_value_discrete_impl.d.ts +0 -52
  297. package/dist/src/data_access/ua_multistate_value_discrete_impl.js +0 -254
  298. package/dist/src/data_access/ua_multistate_value_discrete_impl.js.map +0 -1
  299. package/dist/src/data_access/ua_two_state_discrete_impl.d.ts +0 -25
  300. package/dist/src/data_access/ua_two_state_discrete_impl.js +0 -154
  301. package/dist/src/data_access/ua_two_state_discrete_impl.js.map +0 -1
  302. package/dist/src/event_data.d.ts +0 -34
  303. package/dist/src/event_data.js +0 -65
  304. package/dist/src/event_data.js.map +0 -1
  305. package/dist/src/extension_object_array_node.d.ts +0 -23
  306. package/dist/src/extension_object_array_node.js +0 -249
  307. package/dist/src/extension_object_array_node.js.map +0 -1
  308. package/dist/src/historical_access/address_space_historical_data_node.d.ts +0 -26
  309. package/dist/src/historical_access/address_space_historical_data_node.js +0 -653
  310. package/dist/src/historical_access/address_space_historical_data_node.js.map +0 -1
  311. package/dist/src/idx_iterator.d.ts +0 -8
  312. package/dist/src/idx_iterator.js +0 -51
  313. package/dist/src/idx_iterator.js.map +0 -1
  314. package/dist/src/index_current.d.ts +0 -46
  315. package/dist/src/index_current.js +0 -78
  316. package/dist/src/index_current.js.map +0 -1
  317. package/dist/src/namespace_impl.d.ts +0 -456
  318. package/dist/src/namespace_impl.js +0 -1763
  319. package/dist/src/namespace_impl.js.map +0 -1
  320. package/dist/src/namespace_private.d.ts +0 -23
  321. package/dist/src/namespace_private.js +0 -33
  322. package/dist/src/namespace_private.js.map +0 -1
  323. package/dist/src/nodeid_manager.d.ts +0 -37
  324. package/dist/src/nodeid_manager.js +0 -184
  325. package/dist/src/nodeid_manager.js.map +0 -1
  326. package/dist/src/nodeset_tools/adjust_namespace_array.d.ts +0 -2
  327. package/dist/src/nodeset_tools/adjust_namespace_array.js +0 -14
  328. package/dist/src/nodeset_tools/adjust_namespace_array.js.map +0 -1
  329. package/dist/src/nodeset_tools/construct_namespace_dependency.d.ts +0 -18
  330. package/dist/src/nodeset_tools/construct_namespace_dependency.js +0 -141
  331. package/dist/src/nodeset_tools/construct_namespace_dependency.js.map +0 -1
  332. package/dist/src/nodeset_tools/dump_to_bsd.d.ts +0 -2
  333. package/dist/src/nodeset_tools/dump_to_bsd.js +0 -164
  334. package/dist/src/nodeset_tools/dump_to_bsd.js.map +0 -1
  335. package/dist/src/nodeset_tools/nodeset_to_xml.d.ts +0 -10
  336. package/dist/src/nodeset_tools/nodeset_to_xml.js +0 -1288
  337. package/dist/src/nodeset_tools/nodeset_to_xml.js.map +0 -1
  338. package/dist/src/private_namespace.d.ts +0 -5
  339. package/dist/src/private_namespace.js +0 -20
  340. package/dist/src/private_namespace.js.map +0 -1
  341. package/dist/src/reference_impl.d.ts +0 -43
  342. package/dist/src/reference_impl.js +0 -140
  343. package/dist/src/reference_impl.js.map +0 -1
  344. package/dist/src/role_permissions.d.ts +0 -2
  345. package/dist/src/role_permissions.js +0 -11
  346. package/dist/src/role_permissions.js.map +0 -1
  347. package/dist/src/state_machine/finite_state_machine.d.ts +0 -81
  348. package/dist/src/state_machine/finite_state_machine.js +0 -389
  349. package/dist/src/state_machine/finite_state_machine.js.map +0 -1
  350. package/dist/src/state_machine/ua_shelving_state_machine_ex.d.ts +0 -38
  351. package/dist/src/state_machine/ua_shelving_state_machine_ex.js +0 -251
  352. package/dist/src/state_machine/ua_shelving_state_machine_ex.js.map +0 -1
  353. package/dist/src/state_machine/ua_two_state_variable.d.ts +0 -61
  354. package/dist/src/state_machine/ua_two_state_variable.js +0 -332
  355. package/dist/src/state_machine/ua_two_state_variable.js.map +0 -1
  356. package/dist/src/tool_isSubtypeOf.d.ts +0 -18
  357. package/dist/src/tool_isSubtypeOf.js +0 -125
  358. package/dist/src/tool_isSubtypeOf.js.map +0 -1
  359. package/dist/src/tool_isSupertypeOf.d.ts +0 -18
  360. package/dist/src/tool_isSupertypeOf.js +0 -125
  361. package/dist/src/tool_isSupertypeOf.js.map +0 -1
  362. package/dist/src/ua_condition_type.d.ts +0 -8
  363. package/dist/src/ua_condition_type.js +0 -3
  364. package/dist/src/ua_condition_type.js.map +0 -1
  365. package/dist/src/ua_data_type_impl.d.ts +0 -89
  366. package/dist/src/ua_data_type_impl.js +0 -369
  367. package/dist/src/ua_data_type_impl.js.map +0 -1
  368. package/dist/src/ua_method_impl.d.ts +0 -42
  369. package/dist/src/ua_method_impl.js +0 -218
  370. package/dist/src/ua_method_impl.js.map +0 -1
  371. package/dist/src/ua_object_impl.d.ts +0 -35
  372. package/dist/src/ua_object_impl.js +0 -169
  373. package/dist/src/ua_object_impl.js.map +0 -1
  374. package/dist/src/ua_object_type_impl.d.ts +0 -50
  375. package/dist/src/ua_object_type_impl.js +0 -127
  376. package/dist/src/ua_object_type_impl.js.map +0 -1
  377. package/dist/src/ua_reference_type_impl.d.ts +0 -45
  378. package/dist/src/ua_reference_type_impl.js +0 -142
  379. package/dist/src/ua_reference_type_impl.js.map +0 -1
  380. package/dist/src/ua_variable_impl.d.ts +0 -380
  381. package/dist/src/ua_variable_impl.js +0 -1738
  382. package/dist/src/ua_variable_impl.js.map +0 -1
  383. package/dist/src/ua_variable_impl_ext_obj.d.ts +0 -23
  384. package/dist/src/ua_variable_impl_ext_obj.js +0 -671
  385. package/dist/src/ua_variable_impl_ext_obj.js.map +0 -1
  386. package/dist/src/ua_variable_type_impl.d.ts +0 -74
  387. package/dist/src/ua_variable_type_impl.js +0 -582
  388. package/dist/src/ua_variable_type_impl.js.map +0 -1
  389. package/dist/src/ua_view_impl.d.ts +0 -19
  390. package/dist/src/ua_view_impl.js +0 -44
  391. package/dist/src/ua_view_impl.js.map +0 -1
  392. package/distHelpers/add_event_generator_object.d.ts +0 -3
  393. package/distHelpers/add_event_generator_object.js +0 -65
  394. package/distHelpers/add_event_generator_object.js.map +0 -1
  395. package/distHelpers/alarms_and_conditions_demo.d.ts +0 -9
  396. package/distHelpers/alarms_and_conditions_demo.js +0 -116
  397. package/distHelpers/alarms_and_conditions_demo.js.map +0 -1
  398. package/distHelpers/assertHasMatchingReference.d.ts +0 -19
  399. package/distHelpers/assertHasMatchingReference.js +0 -41
  400. package/distHelpers/assertHasMatchingReference.js.map +0 -1
  401. package/distHelpers/boiler_system.d.ts +0 -113
  402. package/distHelpers/boiler_system.js +0 -396
  403. package/distHelpers/boiler_system.js.map +0 -1
  404. package/distHelpers/create_minimalist_address_space_nodeset.d.ts +0 -5
  405. package/distHelpers/create_minimalist_address_space_nodeset.js +0 -172
  406. package/distHelpers/create_minimalist_address_space_nodeset.js.map +0 -1
  407. package/distHelpers/date_utils.d.ts +0 -3
  408. package/distHelpers/date_utils.js +0 -10
  409. package/distHelpers/date_utils.js.map +0 -1
  410. package/distHelpers/dump_statemachine.d.ts +0 -0
  411. package/distHelpers/dump_statemachine.js +0 -128
  412. package/distHelpers/dump_statemachine.js.map +0 -1
  413. package/distHelpers/get_address_space_fixture.d.ts +0 -1
  414. package/distHelpers/get_address_space_fixture.js +0 -31
  415. package/distHelpers/get_address_space_fixture.js.map +0 -1
  416. package/distHelpers/get_mini_address_space.d.ts +0 -7
  417. package/distHelpers/get_mini_address_space.js +0 -37
  418. package/distHelpers/get_mini_address_space.js.map +0 -1
  419. package/distHelpers/index.d.ts +0 -12
  420. package/distHelpers/index.js +0 -29
  421. package/distHelpers/index.js.map +0 -1
  422. package/distHelpers/mock_session.d.ts +0 -10
  423. package/distHelpers/mock_session.js +0 -26
  424. package/distHelpers/mock_session.js.map +0 -1
  425. package/distNodeJS/generate_address_space.d.ts +0 -6
  426. package/distNodeJS/generate_address_space.js +0 -53
  427. package/distNodeJS/generate_address_space.js.map +0 -1
  428. package/distNodeJS/index.d.ts +0 -1
  429. package/distNodeJS/index.js +0 -18
  430. package/distNodeJS/index.js.map +0 -1
  431. package/source/helpers/dump_tools.ts +0 -92
  432. package/src/nodeset_tools/dump_to_bsd.ts +0 -196
  433. package/test_helpers/dump_statemachine.ts +0 -155
@@ -1,2305 +1,2307 @@
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;
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
- function is_Variant_or_StatusCode(v: any): boolean {
150
- if (is_Variant(v)) {
151
- // /@@assert(v.isValid());
152
- }
153
- return is_Variant(v) || is_StatusCode(v);
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
- function _dataType_toUADataType(addressSpace: IAddressSpace, dataType: DataType): UADataType {
157
- assert(addressSpace);
158
- assert(dataType !== DataType.Null);
156
+ function _dataType_toUADataType(addressSpace: IAddressSpace, dataType: DataType): UADataType {
157
+ assert(addressSpace);
158
+ assert(dataType !== DataType.Null);
159
159
 
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");
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
- * @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;
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
- const destUADataType = addressSpace.findDataType(dataTypeNodeId)!;
195
- assert(destUADataType instanceof UADataTypeImpl);
194
+ const destUADataType = addressSpace.findDataType(dataTypeNodeId)!;
195
+ assert(destUADataType instanceof UADataTypeImpl);
196
196
 
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);
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
- 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
- );
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
- // 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);
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
- const dest_isSubTypeOf_variant = variantUADataType.isSubtypeOf(builtInUADataType);
226
+ const dest_isSubTypeOf_variant = variantUADataType.isSubtypeOf(builtInUADataType);
227
227
 
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());
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
- return dest_isSubTypeOf_variant;
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
- function default_func(this: UAVariable, dataValue1: DataValue, callback1: CallbackT<StatusCode>) {
246
- return _default_writable_timestamped_set_func.call(this, dataValue1, callback1);
247
- }
242
+ return dest_isSubTypeOf_variant;
243
+ }
248
244
 
249
- interface UAVariableOptions extends InternalBaseNodeOptions {
250
- value?: any;
251
- dataType: NodeId | string;
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
- * 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
- *
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
- 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
- );
335
- }
336
- return super.typeDefinitionObj as UAVariableType;
337
- }
338
- get typeDefinition(): NodeId {
339
- return super.typeDefinition;
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
- constructor(options: UAVariableOptions) {
342
- super(options);
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
- verifyRankAndDimensions(options);
345
- this.valueRank = options.valueRank!;
346
- this.arrayDimensions = options.arrayDimensions!;
344
+ verifyRankAndDimensions(options);
345
+ this.valueRank = options.valueRank!;
346
+ this.arrayDimensions = options.arrayDimensions!;
347
347
 
348
- this.dataType = this.resolveNodeId(options.dataType); // DataType (NodeId)
348
+ this.dataType = this.resolveNodeId(options.dataType); // DataType (NodeId)
349
349
 
350
- this.accessLevel = adjust_accessLevel(options.accessLevel);
350
+ this.accessLevel = adjust_accessLevel(options.accessLevel);
351
351
 
352
- this.userAccessLevel = adjust_userAccessLevel(options.userAccessLevel, this.accessLevel);
352
+ this.userAccessLevel = adjust_userAccessLevel(options.userAccessLevel, this.accessLevel);
353
353
 
354
- this.minimumSamplingInterval = adjust_samplingInterval(options.minimumSamplingInterval || 0);
354
+ this.minimumSamplingInterval = adjust_samplingInterval(options.minimumSamplingInterval || 0);
355
355
 
356
- this.historizing = !!options.historizing; // coerced to boolean"
356
+ this.historizing = !!options.historizing; // coerced to boolean"
357
357
 
358
- this.$dataValue = new DataValue({ statusCode: StatusCodes.UncertainInitialValue, value: { dataType: DataType.Null } });
358
+ this.$dataValue = new DataValue({ statusCode: StatusCodes.UncertainInitialValue, value: { dataType: DataType.Null } });
359
359
 
360
- if (options.value) {
361
- this.bindVariable(options.value);
362
- }
360
+ if (options.value) {
361
+ this.bindVariable(options.value);
362
+ }
363
363
 
364
- this.setMaxListeners(5000);
364
+ this.setMaxListeners(5000);
365
365
 
366
- this.semantic_version = 0;
367
- }
368
- private checkAccessLevelPrivate(
369
- _context: ISessionContext,
370
- accessLevel: AccessLevelFlag): boolean {
371
- if (this.userAccessLevel === undefined) {
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
- 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
- }
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 (!this.checkPermissionPrivate(context, PermissionType.Read)) {
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
- public isWritable(context: ISessionContext): boolean {
418
- return (this.accessLevel & AccessLevelFlag.CurrentWrite) === AccessLevelFlag.CurrentWrite;
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
- public isUserWritable(context: ISessionContext): boolean {
422
- if (!this.isWritable(context)) {
423
- return false;
424
- }
425
- return this.checkPermissionAndAccessLevelPrivate(context, PermissionType.Write, AccessLevelFlag.CurrentWrite);
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
- public canUserReadHistory(context: ISessionContext): boolean {
429
- return this.checkPermissionAndAccessLevelPrivate(context, PermissionType.ReadHistory, AccessLevelFlag.HistoryRead);
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
- public canUserWriteHistorizingAttribute(context: ISessionContext): boolean {
432
- if (context && !context.checkPermission(this, PermissionType.WriteHistorizing)) {
433
- return false;
434
- }
435
- return true;
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
- if (context.isAccessRestricted(this)) {
484
- return new DataValue({ statusCode: StatusCodes.BadSecurityModeInsufficient });
485
- }
483
+ if (context.isAccessRestricted(this)) {
484
+ return new DataValue({ statusCode: StatusCodes.BadSecurityModeInsufficient });
485
+ }
486
486
 
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
- }
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
- 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);
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
- let dataValue = this.$dataValue;
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
- /* 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
- );
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
- public isEnumeration(): boolean {
539
- return this.addressSpacePrivate.isEnumeration(this.dataType);
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
- * 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");
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
- 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();
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
- 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
- }
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
- 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
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
- if (this.$dataValue.serverTimestamp && oldestDate.getTime() <= this.$dataValue.serverTimestamp!.getTime()) {
592
- const dataValue = this.readValue().clone();
593
- dataValue.serverTimestamp = oldestDate;
594
- dataValue.serverPicoseconds = 0;
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
- 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 : "?????" };
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
- public writeEnumValue(value: string | number): void {
631
- const enumInfo = this._getEnumerationInfo();
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
- if (typeof value === "string") {
634
- if (!Object.prototype.hasOwnProperty.call(enumInfo.nameIndex, value)) {
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)) {
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
- if (!enumInfo.valueIndex[value]) {
645
- throw new Error("UAVariable#writeEnumValue : value out of range " + value + " in [" + possibleValues + "]");
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
- 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);
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
- const options: DataValueLike = {};
665
+ const options: DataValueLike = {};
666
666
 
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);
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
- switch (attributeId) {
679
- case AttributeIds.Value:
680
- return this.readValue(context, indexRange, dataEncoding);
678
+ switch (attributeId) {
679
+ case AttributeIds.Value:
680
+ return this.readValue(context, indexRange, dataEncoding);
681
681
 
682
- case AttributeIds.DataType:
683
- return this._readDataType();
682
+ case AttributeIds.DataType:
683
+ return this._readDataType();
684
684
 
685
- case AttributeIds.ValueRank:
686
- return this._readValueRank();
685
+ case AttributeIds.ValueRank:
686
+ return this._readValueRank();
687
687
 
688
- case AttributeIds.ArrayDimensions:
689
- return this._readArrayDimensions();
688
+ case AttributeIds.ArrayDimensions:
689
+ return this._readArrayDimensions();
690
690
 
691
- case AttributeIds.AccessLevel:
692
- return this._readAccessLevel(context);
691
+ case AttributeIds.AccessLevel:
692
+ return this._readAccessLevel(context);
693
693
 
694
- case AttributeIds.UserAccessLevel:
695
- return this._readUserAccessLevel(context);
694
+ case AttributeIds.UserAccessLevel:
695
+ return this._readUserAccessLevel(context);
696
696
 
697
- case AttributeIds.MinimumSamplingInterval:
698
- return this._readMinimumSamplingInterval();
697
+ case AttributeIds.MinimumSamplingInterval:
698
+ return this._readMinimumSamplingInterval();
699
699
 
700
- case AttributeIds.Historizing:
701
- return this._readHistorizing();
700
+ case AttributeIds.Historizing:
701
+ return this._readHistorizing();
702
702
 
703
- case AttributeIds.AccessLevelEx:
704
- return this._readAccessLevelEx(context);
705
- default:
706
- return BaseNodeImpl.prototype.readAttribute.call(this, context, attributeId);
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
- public getBasicDataType(): DataType {
711
- if (this._basicDataType) {
712
- return this._basicDataType;
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
- public adjustVariant(variant: Variant): Variant {
730
- return adjustVariant(variant, this.valueRank, this.getBasicDataType());
714
+ if (this.dataType.namespace === 0 && this.dataType.value === 0) {
715
+ return DataType.Null;
731
716
  }
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
- );
743
- }
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
- );
754
- }
755
- if (
756
- this.dataType.namespace === 0 &&
757
- this.dataType.value === DataType.LocalizedText &&
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 (basicType === DataType.ByteString && variant.dataType === DataType.String) {
775
- return; // this is allowed
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
- basicType !== DataType.Null &&
780
- basicType !== DataType.Variant &&
781
- variant.dataType !== DataType.Null &&
782
- variant.dataType !== basicType
756
+ this.dataType.namespace === 0 &&
757
+ this.dataType.value === DataType.LocalizedText &&
758
+ variant.dataType !== DataType.LocalizedText &&
759
+ variant.dataType !== DataType.Null
783
760
  ) {
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);
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
- * 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;
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
- 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);
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
- const { timestamp, picoseconds } = getCurrentClock();
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
- if (context.currentTime && !dataValue.serverTimestamp) {
895
- dataValue.serverTimestamp = context.currentTime.timestamp;
896
- dataValue.serverPicoseconds = context.currentTime.picoseconds;
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
- // 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];
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
- throw new Error("Invalid Number of args");
888
+ const { timestamp, picoseconds } = getCurrentClock();
889
+ dataValue.sourceTimestamp = timestamp;
890
+ dataValue.sourcePicoseconds = picoseconds;
910
891
  }
892
+ }
911
893
 
912
- assert(typeof callback === "function");
913
- assert(dataValue instanceof DataValue);
914
- // index range could be string
915
- indexRange = NumericRange.coerce(indexRange);
894
+ if (context.currentTime && !dataValue.serverTimestamp) {
895
+ dataValue.serverTimestamp = context.currentTime.timestamp;
896
+ dataValue.serverPicoseconds = context.currentTime.picoseconds;
897
+ }
916
898
 
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
- }
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
- if (!this.isUserWritable(context)) {
927
- return callback!(null, StatusCodes.BadWriteNotSupported);
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
- const statusCode = this.checkVariantCompatibility(variant);
934
- if (statusCode.isNot(StatusCodes.Good)) {
935
- return callback!(null, statusCode);
936
- }
926
+ if (!this.isUserWritable(context)) {
927
+ return callback!(null, StatusCodes.BadWriteNotSupported);
928
+ }
937
929
 
938
- const write_func = this._timestamped_set_func || default_func;
930
+ // adjust special case
931
+ const variant = adjustVariant2.call(this, dataValue.value);
939
932
 
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);
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
- write_func.call(this, dataValue, (err?: Error | null, statusCode1?: StatusCode) => {
948
- if (!err) {
949
- dataValue && this.verifyVariantCompatibility(dataValue.value);
947
+ write_func.call(this, dataValue, (err?: Error | null, statusCode1?: StatusCode) => {
948
+ if (!err) {
949
+ dataValue && this.verifyVariantCompatibility(dataValue.value);
950
950
 
951
- if (indexRange && !indexRange.isEmpty()) {
952
- if (!indexRange.isValid()) {
953
- return callback!(null, StatusCodes.BadIndexRangeInvalid);
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
- 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);
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);
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
- try {
1001
- this._internal_set_dataValue(dataValue, indexRange);
1002
- } catch (err) {
1003
- if (err instanceof Error) {
1004
- warningLog(err.message);
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
- return callback!(null, StatusCodes.BadInternalError);
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
- callback!(err || null, statusCode1);
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
- 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
- }
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
- 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
- }
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
- if (!this.canUserWriteHistorizingAttribute(context)) {
1058
- return callback(null, StatusCodes.BadHistoryOperationUnsupported);
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
- // 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;
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
- * @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
- }
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
- options = options || {};
1263
+ assert(typeof callback === "function");
1236
1264
 
1237
- assert(typeof this._timestamped_set_func !== "function", "UAVariable already bound");
1238
- assert(typeof this._timestamped_get_func !== "function", "UAVariable already bound");
1265
+ context = context || SessionContext.defaultContext;
1239
1266
 
1240
- bind_getter.call(this, options);
1241
- bind_setter.call(this, options);
1267
+ this.__waiting_callbacks = this.__waiting_callbacks || [];
1268
+ this.__waiting_callbacks.push(callback);
1242
1269
 
1243
- const _historyRead = options.historyRead;
1244
- if (_historyRead) {
1245
- assert(typeof this._historyRead !== "function" || this._historyRead === UAVariableImpl.prototype._historyRead);
1246
- assert(typeof _historyRead === "function");
1270
+ const _readValueAsync_in_progress = this.__waiting_callbacks.length >= 2;
1271
+ if (_readValueAsync_in_progress) {
1272
+ return;
1273
+ }
1247
1274
 
1248
- this._historyRead = _historyRead;
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
- this.__waiting_callbacks = this.__waiting_callbacks || [];
1268
- this.__waiting_callbacks.push(callback);
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
- const _readValueAsync_in_progress = this.__waiting_callbacks.length >= 2;
1271
- if (_readValueAsync_in_progress) {
1272
- return;
1273
- }
1283
+ let func: (innerCallback: (err: Error | null, dataValue: DataValue) => void) => void;
1274
1284
 
1275
- const readImmediate = (innerCallback: (err: Error | null, dataValue: DataValue) => void) => {
1276
- assert(this.$dataValue instanceof DataValue);
1277
- const dataValue = this.readValue();
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
- let func: (innerCallback: (err: Error | null, dataValue: DataValue) => void) => void;
1282
-
1283
- if (!this.isReadable(context)) {
1284
- func = (innerCallback: (err: Error | null, dataValue: DataValue) => void) => {
1285
- const dataValue = new DataValue({ statusCode: StatusCodes.BadNotReadable });
1286
- innerCallback(null, dataValue);
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
- try {
1314
- func.call(this, satisfy_callbacks);
1315
- } catch (err) {
1316
- // istanbul ignore next
1317
- if (doDebug) {
1318
- debugLog(chalk.red("func readValueAsync has failed "));
1319
- if (err instanceof Error) {
1320
- debugLog(" stack", err.stack);
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
- public getWriteMask(): number {
1328
- return super.getWriteMask();
1329
- }
1330
-
1331
- public getUserWriteMask(): number {
1332
- return super.getUserWriteMask();
1333
- }
1329
+ public getWriteMask(): number {
1330
+ return super.getWriteMask();
1331
+ }
1334
1332
 
1335
- public clone(options: CloneOptions, optionalFilter?: CloneFilter, extraInfo?: CloneExtraInfo): UAVariable {
1336
- options = {
1337
- ...options,
1338
- // check this eventNotifier: this.eventNotifier,
1339
- // check this symbolicName: this.symbolicName,
1333
+ public getUserWriteMask(): number {
1334
+ return super.getUserWriteMask();
1335
+ }
1340
1336
 
1341
- accessLevel: this.accessLevel,
1342
- arrayDimensions: this.arrayDimensions,
1343
- dataType: this.dataType,
1344
- historizing: this.historizing,
1345
- minimumSamplingInterval: this.minimumSamplingInterval,
1346
- userAccessLevel: this.userAccessLevel,
1347
- valueRank: this.valueRank
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
- const newVariable = _clone.call(
1351
- this,
1352
- UAVariableImpl,
1353
- options,
1354
- optionalFilter || defaultCloneFilter,
1355
- extraInfo || defaultCloneExtraInfo
1356
- ) as UAVariableImpl;
1352
+ const newVariable = _clone.call(
1353
+ this,
1354
+ UAVariableImpl,
1355
+ options,
1356
+ optionalFilter || defaultCloneFilter,
1357
+ extraInfo || defaultCloneExtraInfo
1358
+ ) as UAVariableImpl;
1357
1359
 
1358
- newVariable.bindVariable();
1360
+ newVariable.bindVariable();
1359
1361
 
1360
- assert(typeof newVariable._timestamped_set_func === "function");
1362
+ assert(typeof newVariable._timestamped_set_func === "function");
1361
1363
 
1362
- assert(newVariable.dataType === this.dataType);
1363
- newVariable.$dataValue = this.$dataValue.clone();
1364
+ assert(newVariable.dataType === this.dataType);
1365
+ newVariable.$dataValue = this.$dataValue.clone();
1364
1366
 
1365
- // also bind extension object
1366
- const v = newVariable.$dataValue.value;
1367
- if (v.dataType === DataType.ExtensionObject && v.value && v.arrayType === VariantArrayType.Scalar) {
1368
- try {
1369
- newVariable.bindExtensionObject(newVariable.$dataValue.value.value);
1370
- } catch (err) {
1371
- errorLog("Errro binding extension objects");
1372
- errorLog((err as Error).message);
1373
- errorLog(this.toString());
1374
- errorLog("---------------------------------------");
1375
- errorLog(this.$dataValue.toString());
1376
- errorLog("---------------------------------------");
1377
- errorLog(newVariable.$dataValue.toString());
1378
- throw err;
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
- public getDataTypeNode(): UADataType {
1385
- const addressSpace = this.addressSpace;
1386
- const dt = addressSpace.findNode(this.dataType);
1387
- // istanbul ignore next
1388
- if (!dt) {
1389
- throw new Error("getDataTypeNode: cannot find dataType " + this.dataType.toString());
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
- public get dataTypeObj(): UADataType {
1395
- return this.getDataTypeNode();
1396
- }
1396
+ public get dataTypeObj(): UADataType {
1397
+ return this.getDataTypeNode();
1398
+ }
1397
1399
 
1398
- public checkExtensionObjectIsCorrect(extObj: ExtensionObject | ExtensionObject[] | null): boolean {
1399
- if (!extObj) {
1400
- return true;
1401
- }
1402
- const addressSpace = this.addressSpace;
1403
- const dataType = addressSpace.findDataType(this.dataType);
1404
- if (!dataType) {
1405
- // may be we are in the process of loading a xml file and the corresponding dataType
1406
- // has not yet been loaded !
1407
- return true;
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
- const Constructor = addressSpace.getExtensionObjectConstructor(this.dataType);
1412
+ const Constructor = addressSpace.getExtensionObjectConstructor(this.dataType);
1411
1413
 
1412
- if (this.valueRank === -1) {
1413
- /** Scalar */
1414
- if (extObj instanceof Array) {
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
- function checkExtensionObjectIsCorrectScalar(
1444
- this: UAVariableImpl,
1445
- extObj: ExtensionObject | ExtensionObject[] | null
1446
- ): boolean {
1447
- // istanbul ignore next
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
- function checkExtensionObjectIsCorrectArray(this: UAVariableImpl, extObjArray: ExtensionObject[]): boolean {
1456
- // istanbul ignore next
1457
- for (const extObj of extObjArray) {
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
- try {
1464
- for (const e of extObjArray) {
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
- * @private
1483
- * install UAVariable to exposed th
1484
- *
1485
- * precondition:
1486
- */
1487
- public installExtensionObjectVariables(): void {
1488
- _installExtensionObjectBindingOnProperties(this, { createMissingProp: true });
1489
- }
1490
- /**
1491
- * @method bindExtensionObject
1492
- * @return {ExtensionObject}
1493
- */
1494
- public bindExtensionObjectScalar(
1495
- optionalExtensionObject?: ExtensionObject,
1496
- options?: BindExtensionObjectOptions
1497
- ): ExtensionObject | null {
1498
- assert(this.valueRank === -1, "expecting an Scalar variable here");
1499
- return _bindExtensionObject(this, optionalExtensionObject, options) as ExtensionObject;
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
- if (optionalExtensionObject) {
1522
- if (optionalExtensionObject instanceof Array) {
1523
- assert(this.valueRank >= 1, "bindExtensionObject: expecting an Array of Matrix variable here");
1524
- return _bindExtensionObjectArrayOrMatrix(this, optionalExtensionObject, options);
1525
- } else {
1526
- if (this.valueRank !== -1 && this.valueRank !== 0) {
1527
- throw new Error("bindExtensionObject: expecting an Scalar variable here but got value rank " + this.valueRank);
1528
- }
1529
- return _bindExtensionObject(this, optionalExtensionObject, options) as ExtensionObject;
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
- assert(optionalExtensionObject === undefined);
1533
- if (this.valueRank === -1) {
1534
- return _bindExtensionObject(this, undefined, options) as ExtensionObject;
1535
- } else if (this.valueRank === 1) {
1536
- return _bindExtensionObjectArrayOrMatrix(this, undefined, options);
1537
- } else if (this.valueRank > 1) {
1538
- return _bindExtensionObjectArrayOrMatrix(this, undefined, options);
1539
- }
1540
- // unsupported case ...
1541
- return null;
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
- this._historyRead(context, historyReadDetails, indexRange, dataEncoding, continuationData, callback!);
1612
- }
1613
-
1614
- public _historyReadRaw(
1615
- context: ISessionContext,
1616
- historyReadRawModifiedDetails: ReadRawModifiedDetails,
1617
- indexRange: NumericRange | null,
1618
- dataEncoding: QualifiedNameLike | null,
1619
- continuationData: ContinuationData,
1620
- callback: CallbackT<HistoryReadResult>
1621
- ): void {
1622
- throw new Error("");
1623
- }
1624
-
1625
- public _historyReadRawModify(
1626
- context: ISessionContext,
1627
- historyReadRawModifiedDetails: ReadRawModifiedDetails,
1628
- indexRange: NumericRange | null,
1629
- dataEncoding: QualifiedNameLike | null,
1630
- continuationData: ContinuationData,
1631
- callback?: CallbackT<HistoryReadResult>
1632
- ): any {
1633
- throw new Error("");
1634
- }
1635
-
1636
- public _historyRead(
1637
- context: ISessionContext,
1638
- historyReadDetails:
1639
- | HistoryReadDetails
1640
- | ReadRawModifiedDetails
1641
- | ReadEventDetails
1642
- | ReadProcessedDetails
1643
- | ReadAtTimeDetails,
1644
- indexRange: NumericRange | null,
1645
- dataEncoding: QualifiedNameLike | null,
1646
- continuationData: ContinuationData,
1647
- callback: CallbackT<HistoryReadResult>
1648
- ): void {
1649
-
1650
- if (!this.checkPermissionPrivate(context, PermissionType.ReadHistory)) {
1651
- const result = new HistoryReadResult({
1652
- statusCode: StatusCodes.BadUserAccessDenied
1653
- });
1654
- callback(null, result);
1655
- }
1656
- if (!this.canUserReadHistory(context)) {
1657
- const result = new HistoryReadResult({
1658
- statusCode: StatusCodes.BadHistoryOperationUnsupported
1659
- });
1660
- callback(null, result);
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
- public _historyPush(newDataValue: DataValue): any {
1669
- throw new Error("");
1670
- }
1670
+ public _historyPush(newDataValue: DataValue): any {
1671
+ throw new Error("");
1672
+ }
1671
1673
 
1672
- public _historyReadRawAsync(
1673
- historyReadRawModifiedDetails: ReadRawModifiedDetails,
1674
- maxNumberToExtract: number,
1675
- isReversed: boolean,
1676
- reverseDataValue: boolean,
1677
- callback: CallbackT<DataValue[]>
1678
- ): any {
1679
- throw new Error("");
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
- public _historyReadModify(
1683
- context: ISessionContext,
1684
- historyReadRawModifiedDetails: ReadRawModifiedDetails,
1685
- indexRange: NumericRange | null,
1686
- dataEncoding: QualifiedNameLike | null,
1687
- continuationData: ContinuationData,
1688
- callback: CallbackT<HistoryReadResult>
1689
- ): any {
1690
- throw new Error("");
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
- public _update_startOfOnlineArchive(newDate: Date): void {
1694
- // please install
1695
- throw new Error("");
1696
- }
1695
+ public _update_startOfOnlineArchive(newDate: Date): void {
1696
+ // please install
1697
+ throw new Error("");
1698
+ }
1697
1699
 
1698
- public _update_startOfArchive(newDate: Date): void {
1699
- throw new Error("");
1700
- }
1700
+ public _update_startOfArchive(newDate: Date): void {
1701
+ throw new Error("");
1702
+ }
1701
1703
 
1702
- public _validate_DataType(variantDataType: DataType): boolean {
1703
- return validateDataType(this.addressSpace, this.dataType, variantDataType, this.nodeId, /* allow Nulls */ false);
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
- public _internal_set_value(value: Variant): void {
1707
- if (value.dataType !== DataType.Null) {
1708
- this.verifyVariantCompatibility(value);
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
- public _internal_set_dataValue(dataValue: DataValue, indexRange?: NumericRange | null): void {
1714
- assert(dataValue, "expecting a dataValue");
1715
- assert(dataValue instanceof DataValue, "expecting dataValue to be a DataValue");
1716
- assert(dataValue !== this.$dataValue, "expecting dataValue to be different from previous DataValue instance");
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
- const addressSpace = this.addressSpace;
1720
+ const addressSpace = this.addressSpace;
1719
1721
 
1720
- // istanbul ignore next
1721
- if (!addressSpace) {
1722
- warningLog("UAVariable#_internal_set_dataValue : no addressSpace ! may be node has already been deleted ?");
1723
- return;
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
- // istanbul ignore next
1727
- if (dataValue.value.arrayType === VariantArrayType.Matrix) {
1728
- if (!dataValue.value.dimensions) {
1729
- throw new Error("missing dimensions: a Matrix Variant needs a dimension");
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.dataType === DataType.ExtensionObject) {
1742
- // istanbul ignore next
1743
- if (!this.checkExtensionObjectIsCorrect(dataValue.value.value)) {
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
- assert(this.$dataValue.value instanceof Variant);
1760
- const old_dataValue = this.$dataValue.clone();
1753
+ this._inner_replace_dataValue(dataValue, indexRange);
1754
+ }
1761
1755
 
1762
- if (this.$$extensionObjectArray && dataValue.value.arrayType !== VariantArrayType.Scalar) {
1763
- // we have a bounded array or matrix
1764
- assert(Array.isArray(dataValue.value.value));
1765
- if (this.$$extensionObjectArray !== this.$dataValue.value.value) {
1766
- throw new Error("internal error");
1767
- }
1768
- this.$$extensionObjectArray = dataValue.value.value;
1769
- this.$dataValue.value.value = dataValue.value.value;
1770
-
1771
- this.$dataValue.statusCode = dataValue.statusCode || StatusCodes.Good;
1772
- this.$dataValue.serverTimestamp = dataValue.serverTimestamp;
1773
- this.$dataValue.serverPicoseconds = dataValue.serverPicoseconds;
1774
- this.$dataValue.sourceTimestamp = dataValue.sourceTimestamp;
1775
- this.$dataValue.sourcePicoseconds = dataValue.sourcePicoseconds;
1776
-
1777
- } else if (this._basicDataType === DataType.ExtensionObject && this.valueRank === -1 && this.$set_ExtensionObject && dataValue.value.arrayType === VariantArrayType.Scalar) {
1778
- // the entire extension object is changed.
1779
- this.$dataValue.statusCode = this.$dataValue.statusCode || StatusCodes.Good;
1780
- const preciseClock = coerceClock(this.$dataValue.sourceTimestamp, this.$dataValue.sourcePicoseconds);
1781
- this.$set_ExtensionObject(dataValue.value.value, preciseClock, new Set())
1782
- } else {
1783
- this.$dataValue = dataValue;
1784
- this.$dataValue.statusCode = this.$dataValue.statusCode || StatusCodes.Good;
1785
- }
1786
- // repair missing timestamps
1787
- const now = new Date();
1788
- if (!dataValue.serverTimestamp) {
1789
- this.$dataValue.serverTimestamp = old_dataValue.serverTimestamp || now;
1790
- this.$dataValue.serverPicoseconds = old_dataValue.serverPicoseconds || 0;
1791
- }
1792
- if (!dataValue.sourceTimestamp) {
1793
- this.$dataValue.sourceTimestamp = old_dataValue.sourceTimestamp || now;
1794
- this.$dataValue.sourcePicoseconds = old_dataValue.sourcePicoseconds || 0;
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
- if (!sameDataValue(old_dataValue, dataValue)) {
1798
- if (this.getBasicDataType() === DataType.ExtensionObject) {
1799
- const preciseClock = coerceClock(this.$dataValue.sourceTimestamp, this.$dataValue.sourcePicoseconds);
1800
- const cache: Set<UAVariable> = new Set();
1801
- if (this.$$extensionObjectArray) {
1802
- this.touchValue(preciseClock);
1803
- propagateTouchValueDownwardArray(this, preciseClock, cache);
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.emit("value_changed", this.$dataValue.clone(), indexRange);
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
- public _conditionRefresh(_cache?: ConditionRefreshCache): void {
1815
- apply_condition_refresh.call(this, _cache);
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
- private _readDataType(): DataValue {
1824
- assert(this.dataType instanceof NodeId);
1825
- const options = {
1826
- statusCode: StatusCodes.Good,
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
- private _readValueRank(): DataValue {
1836
- assert(typeof this.valueRank === "number");
1837
- const options = {
1838
- statusCode: StatusCodes.Good,
1839
- value: { dataType: DataType.Int32, value: this.valueRank }
1840
- };
1841
- return new DataValue(options);
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
- private _readArrayDimensions(): DataValue {
1845
- assert(Array.isArray(this.arrayDimensions) || this.arrayDimensions === null);
1846
- assert(!this.arrayDimensions || this.valueRank > 0, "arrayDimension must be null if valueRank <0");
1847
- const options = {
1848
- statusCode: StatusCodes.Good,
1849
- value: { dataType: DataType.UInt32, arrayType: VariantArrayType.Array, value: this.arrayDimensions }
1850
- };
1851
- return new DataValue(options);
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
- private _readAccessLevel(context: ISessionContext): DataValue {
1855
- assert(context instanceof SessionContext);
1856
- const options = {
1857
- statusCode: StatusCodes.Good,
1858
- value: { dataType: DataType.Byte, value: convertAccessLevelFlagToByte(this.accessLevel) }
1859
- };
1860
- return new DataValue(options);
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
- private _readAccessLevelEx(context: ISessionContext): DataValue {
1864
- assert(context instanceof SessionContext);
1865
- const options = {
1866
- statusCode: StatusCodes.Good,
1867
- // Extra flags are not supported yet. to do:
1868
- value: { dataType: DataType.UInt32, value: convertAccessLevelFlagToByte(this.accessLevel) }
1869
- };
1870
- return new DataValue(options);
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
- private _readUserAccessLevel(context: ISessionContext): DataValue {
1874
- assert(context instanceof SessionContext);
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
- const effectiveUserAccessLevel = _calculateEffectiveUserAccessLevelFromPermission(this, context, this.userAccessLevel);
1875
+ private _readUserAccessLevel(context: ISessionContext): DataValue {
1876
+ assert(context instanceof SessionContext);
1877
1877
 
1878
- const options = {
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
- private _readMinimumSamplingInterval(): DataValue {
1889
- // expect a Duration => Double
1890
- const options: DataValueLike = {};
1891
- if (this.minimumSamplingInterval === undefined) {
1892
- options.statusCode = StatusCodes.BadAttributeIdInvalid;
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
- return new DataValue(options);
1898
- }
1886
+ };
1887
+ return new DataValue(options);
1888
+ }
1899
1889
 
1900
- private _readHistorizing(): DataValue {
1901
- assert(typeof this.historizing === "boolean");
1902
- const options = {
1903
- statusCode: StatusCodes.Good,
1904
- value: { dataType: DataType.Boolean, value: !!this.historizing }
1905
- };
1906
- return new DataValue(options);
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
- // tslint:disable:no-var-requires
1911
- const thenify = require("thenify");
1912
- UAVariableImpl.prototype.asyncRefresh = thenify.withCallback(UAVariableImpl.prototype.asyncRefresh);
1913
- UAVariableImpl.prototype.writeValue = thenify.withCallback(UAVariableImpl.prototype.writeValue);
1914
- UAVariableImpl.prototype.writeAttribute = thenify.withCallback(UAVariableImpl.prototype.writeAttribute);
1915
- UAVariableImpl.prototype.historyRead = thenify.withCallback(UAVariableImpl.prototype.historyRead);
1916
- UAVariableImpl.prototype.readValueAsync = thenify.withCallback(UAVariableImpl.prototype.readValueAsync);
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
- export interface UAVariableImpl extends UAVariableImplExtArray {
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
- function check_valid_array(dataType: DataType, array: any): boolean {
1928
- if (Array.isArray(array)) {
1929
- return true;
1930
- }
1931
- switch (dataType) {
1932
- case DataType.Double:
1933
- return array instanceof Float64Array;
1934
- case DataType.Float:
1935
- return array instanceof Float32Array;
1936
- case DataType.Int32:
1937
- return array instanceof Int32Array;
1938
- case DataType.Int16:
1939
- return array instanceof Int16Array;
1940
- case DataType.SByte:
1941
- return array instanceof Int8Array;
1942
- case DataType.UInt32:
1943
- return array instanceof Uint32Array;
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
- function _apply_default_timestamps(dataValue: DataValue): void {
1953
- const now = getCurrentClock();
1954
- assert(dataValue instanceof DataValue);
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
- function unsetFlag(flags: number, mask: number): number {
1967
- return flags & ~mask;
1958
+ if (!dataValue.sourceTimestamp) {
1959
+ dataValue.sourceTimestamp = now.timestamp;
1960
+ dataValue.sourcePicoseconds = now.picoseconds;
1968
1961
  }
1969
- function setFlag(flags: number, mask: number): number {
1970
- return flags | mask;
1962
+ if (!dataValue.serverTimestamp) {
1963
+ dataValue.serverTimestamp = now.timestamp;
1964
+ dataValue.serverPicoseconds = now.picoseconds;
1971
1965
  }
1972
-
1973
- function _calculateEffectiveUserAccessLevelFromPermission(
1974
- node: UAVariable,
1975
- context: ISessionContext,
1976
- userAccessLevel: AccessLevelFlag | undefined
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
- function __adjustFlag(
1979
- permissionType: PermissionType,
1980
- access: AccessLevelFlag,
1981
- userAccessLevel1: AccessLevelFlag
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
- function adjustVariant2(this: UAVariableImpl, variant: Variant): Variant {
2008
- // convert Variant( Scalar|ByteString) => Variant(Array|ByteArray)
2009
- const addressSpace = this.addressSpace;
2010
- const basicType = this.getBasicDataType();
2011
- variant = adjustVariant(variant, this.valueRank, basicType);
2012
- return variant;
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
- function _not_writable_timestamped_set_func(
2016
- dataValue: DataValue,
2017
- callback: (err: Error | null, statusCode: StatusCode, dataValue?: DataValue | null) => void
2018
- ) {
2019
- assert(dataValue instanceof DataValue);
2020
- callback(null, StatusCodes.BadNotWritable, null);
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
- function _default_writable_timestamped_set_func(
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
- function turn_sync_to_async<T, D, R>(f: (this: T, data: D) => R, numberOfArgs: number) {
2032
- if (f.length <= numberOfArgs) {
2033
- return function (this: T, data: D, callback: (err: Error | null, r?: R) => void) {
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
- const _default_minimumSamplingInterval = 1000;
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
- function coerceDataValue(dataValue: DataValue | DataValueLike): DataValue {
2048
- if (dataValue instanceof DataValue) {
2049
- return dataValue;
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
- // variation #3 :
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
- assert(typeof options.refreshFunc === "function");
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
- assert(!this.refreshFunc);
2064
-
2065
- this.refreshFunc = options.refreshFunc;
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
- // TO DO : REVISIT THIS ASSUMPTION
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
- // variation 2
2077
- function _Variable_bind_with_timestamped_get(
2078
- this: UAVariableImpl,
2079
- options: {
2080
- get: undefined;
2081
- timestamped_get: TimestampGetFunc;
2082
- }
2083
- ) {
2084
- /* jshint validthis: true */
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
- const async_refresh_func = (callback: (err: Error | null, dataValue?: DataValue) => void) => {
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
- throw new Error(" Bind variable error: " + " the timestamped_get function must return a DataValue");
2116
- }
2117
- _Variable_bind_with_async_refresh.call(this, { refreshFunc: async_refresh_func });
2118
- } else if (options.timestamped_get.length === 1) {
2119
- _Variable_bind_with_async_refresh.call(this, { refreshFunc: options.timestamped_get });
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
- errorLog("timestamped_get has a invalid number of argument , should be 0 or 1 ");
2122
- throw new Error("timestamped_get has a invalid number of argument , should be 0 or 1 ");
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
- // variation 1
2127
- function _Variable_bind_with_simple_get(this: UAVariableImpl, options: GetterOptions) {
2128
- /* jshint validthis: true */
2129
- assert(this instanceof UAVariableImpl);
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
- this._get_func = options.get;
2175
+ assert(!this._timestamped_set_func);
2176
+ assert(!this._set_func);
2137
2177
 
2138
- const timestamped_get_func_from__Variable_bind_with_simple_get = () => {
2139
- const value: Variant | StatusCode = this._get_func();
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
- /* istanbul ignore next */
2142
- if (!is_Variant_or_StatusCode(value)) {
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(" Bind variable error: "),
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
- throw new Error(
2149
- " bindVariable : the value getter function returns a invalid result ( expecting a Variant or a StatusCode !!!"
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
- function _Variable_bind_with_simple_set(this: UAVariableImpl, options: any) {
2169
- assert(this instanceof UAVariableImpl);
2170
- assert(typeof options.set === "function", "should specify set function");
2171
- assert(!options.timestamped_set, "should not specify a timestamped_set function");
2172
-
2173
- assert(!this._timestamped_set_func);
2174
- assert(!this._set_func);
2175
-
2176
- this._set_func = turn_sync_to_async(options.set, 1);
2177
- assert(this._set_func.length === 2, " set function must have 2 arguments ( variant, callback)");
2178
-
2179
- this._timestamped_set_func = (
2180
- timestamped_value: DataValue,
2181
- callback: (err: Error | null, statusCode: StatusCode, dataValue: DataValue) => void
2182
- ) => {
2183
- assert(timestamped_value instanceof DataValue);
2184
- this._set_func(timestamped_value.value, (err: Error | null, statusCode: StatusCode) => {
2185
- // istanbul ignore next
2186
- if (!err && !statusCode) {
2187
- errorLog(
2188
- chalk.red("UAVariable Binding Error _set_func must return a StatusCode, check the bindVariable parameters")
2189
- );
2190
- errorLog(chalk.yellow("StatusCode.Good is assumed"));
2191
- return callback(err, StatusCodes.Good, timestamped_value);
2192
- }
2193
- callback(err, statusCode, timestamped_value);
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
- function _Variable_bind_with_timestamped_set(
2199
- this: UAVariableImpl,
2200
- options: {
2201
- timestamped_set: TimestampSetFunc;
2202
- set: undefined;
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
- options.timestamped_set.length === 2 || options.timestamped_set.length === 1,
2207
- "timestamped_set must have 2 parameters timestamped_set: function(dataValue,callback){} or one paramater timestamped_set: function(dataValue): Promise<StatusCode>{}"
2268
+ !Object.prototype.hasOwnProperty.call(options, "set"),
2269
+ "getter is missing : a getter must be provided if a setter is provided"
2208
2270
  );
2209
- assert(!options.set, "should not specify set when timestamped_set_func exists ");
2210
- this._timestamped_set_func = convertToCallbackFunction1<StatusCode, DataValue, UAVariable>(options.timestamped_set);
2211
- }
2212
-
2213
- interface SetterOptions {
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
- interface GetterOptions {
2245
- get?: GetFunc;
2246
- timestamped_get?: TimestampGetFunc;
2247
- refreshFunc?: (callback: CallbackT<DataValue>) => void;
2248
- dataType?: DataType | string;
2249
- value?: any;
2250
- }
2251
- function bind_getter(this: UAVariableImpl, options: GetterOptions) {
2252
- if (typeof options.get === "function") {
2253
- // variation 1
2254
- _Variable_bind_with_simple_get.call(this, options);
2255
- } else if (typeof options.timestamped_get === "function") {
2256
- // variation 2
2257
- _Variable_bind_with_timestamped_get.call(this, {
2258
- get: undefined,
2259
- timestamped_get: options.timestamped_get
2260
- });
2261
- } else if (typeof options.refreshFunc === "function") {
2262
- // variation 3
2263
- _Variable_bind_with_async_refresh.call(this, options);
2264
- } else {
2265
- assert(
2266
- !Object.prototype.hasOwnProperty.call(options, "set"),
2267
- "getter is missing : a getter must be provided if a setter is provided"
2268
- );
2269
- // xx bind_variant.call(this,options);
2270
- if (options.dataType !== undefined) {
2271
- // if (options.dataType !== DataType.ExtensionObject) {
2272
- this.setValueFromSource(options as VariantLike);
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 { }