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