@adcops/autocore-react 3.1.1 → 3.3.5

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 (252) hide show
  1. package/additional-docs/react_performance_notes.md +94 -0
  2. package/dist/components/AutoCoreDevPanel.d.ts.map +1 -1
  3. package/dist/components/AutoCoreDevPanel.js +1 -1
  4. package/dist/components/FileList.d.ts.map +1 -1
  5. package/dist/components/FileList.js +1 -1
  6. package/dist/components/FileSelect.d.ts.map +1 -1
  7. package/dist/components/FileSelect.js +1 -1
  8. package/dist/core/AutoCoreTagContext.d.ts +59 -185
  9. package/dist/core/AutoCoreTagContext.d.ts.map +1 -1
  10. package/dist/core/AutoCoreTagContext.js +1 -1
  11. package/dist/core/AutoCoreTagTypes.d.ts +127 -6
  12. package/dist/core/AutoCoreTagTypes.d.ts.map +1 -1
  13. package/dist/core/CoreStreamTypes.d.ts +345 -0
  14. package/dist/core/CoreStreamTypes.d.ts.map +1 -0
  15. package/dist/core/CoreStreamTypes.js +1 -0
  16. package/dist/core/EventEmitterContext.d.ts +91 -473
  17. package/dist/core/EventEmitterContext.d.ts.map +1 -1
  18. package/dist/core/EventEmitterContext.js +1 -1
  19. package/dist/hooks/adsHooks.d.ts.map +1 -1
  20. package/dist/hooks/adsHooks.js +1 -1
  21. package/dist/hooks/commandHooks.d.ts +3 -3
  22. package/dist/hooks/commandHooks.d.ts.map +1 -1
  23. package/dist/hooks/commandHooks.js +1 -1
  24. package/dist/hooks/useAutoCoreTag.js +1 -1
  25. package/dist/hub/CommandMessage.d.ts +18 -9
  26. package/dist/hub/CommandMessage.d.ts.map +1 -1
  27. package/dist/hub/CommandMessage.js +1 -1
  28. package/dist/hub/DebugPanel.d.ts +31 -0
  29. package/dist/hub/DebugPanel.d.ts.map +1 -0
  30. package/dist/hub/DebugPanel.js +1 -0
  31. package/dist/hub/HubBase.d.ts +83 -129
  32. package/dist/hub/HubBase.d.ts.map +1 -1
  33. package/dist/hub/HubBase.js +1 -1
  34. package/dist/hub/HubSimulate.d.ts +41 -8
  35. package/dist/hub/HubSimulate.d.ts.map +1 -1
  36. package/dist/hub/HubSimulate.js +1 -1
  37. package/dist/hub/HubTauri.d.ts +24 -60
  38. package/dist/hub/HubTauri.d.ts.map +1 -1
  39. package/dist/hub/HubTauri.js +1 -1
  40. package/dist/hub/HubWebSocket.d.ts +33 -17
  41. package/dist/hub/HubWebSocket.d.ts.map +1 -1
  42. package/dist/hub/HubWebSocket.js +1 -1
  43. package/dist/hub/debug.d.ts +23 -0
  44. package/dist/hub/debug.d.ts.map +1 -0
  45. package/dist/hub/debug.js +1 -0
  46. package/dist/hub/index.d.ts +19 -4
  47. package/dist/hub/index.d.ts.map +1 -1
  48. package/dist/hub/index.js +1 -1
  49. package/package.json +8 -4
  50. package/src/components/AutoCoreDevPanel.tsx +14 -11
  51. package/src/components/FileList.tsx +5 -4
  52. package/src/components/FileSelect.tsx +2 -1
  53. package/src/core/ActionMode.ts +1 -1
  54. package/src/core/AutoCoreTagContext.tsx +247 -330
  55. package/src/core/AutoCoreTagTypes.ts +236 -104
  56. package/src/core/CoreStreamTypes.ts +512 -0
  57. package/src/core/EventEmitterContext.tsx +182 -520
  58. package/src/core/IndicatorButtonState.ts +1 -1
  59. package/src/core/hoc.tsx +1 -1
  60. package/src/hooks/adsHooks.tsx +21 -22
  61. package/src/hooks/commandHooks.tsx +23 -19
  62. package/src/hooks/index.ts +1 -1
  63. package/src/hooks/useAutoCoreTag.ts +2 -2
  64. package/src/hooks/useScaledValue.tsx +1 -1
  65. package/src/hub/CommandMessage.ts +71 -19
  66. package/src/hub/DebugPanel.ts +280 -0
  67. package/src/hub/HubBase.ts +147 -223
  68. package/src/hub/HubSimulate.ts +93 -24
  69. package/src/hub/HubTauri.ts +87 -96
  70. package/src/hub/HubWebSocket.ts +118 -140
  71. package/src/hub/debug.ts +211 -0
  72. package/src/hub/index.ts +49 -39
  73. package/docs/.nojekyll +0 -1
  74. package/docs/assets/hierarchy.js +0 -1
  75. package/docs/assets/highlight.css +0 -134
  76. package/docs/assets/icons.js +0 -18
  77. package/docs/assets/icons.svg +0 -1
  78. package/docs/assets/main.js +0 -60
  79. package/docs/assets/navigation.js +0 -1
  80. package/docs/assets/search.js +0 -1
  81. package/docs/assets/style.css +0 -1633
  82. package/docs/classes/components_CodeEditor.CodeEditor.html +0 -135
  83. package/docs/classes/components_Indicator.Indicator.html +0 -122
  84. package/docs/classes/components_IndicatorRect.IndicatorRect.html +0 -121
  85. package/docs/classes/components_JogPanel.JogPanel.html +0 -136
  86. package/docs/classes/components_Lamp.Lamp.html +0 -122
  87. package/docs/classes/components_OskDialog.OskDialog.html +0 -125
  88. package/docs/classes/components_TextInput.TextInput.html +0 -125
  89. package/docs/classes/components_ValueDisplay.ValueDisplay.html +0 -148
  90. package/docs/classes/components_ValueIndicator.ValueIndicator.html +0 -126
  91. package/docs/classes/core_ValueSimulator.ValueSimulator.html +0 -51
  92. package/docs/classes/hub_HubBase.HubBase.html +0 -106
  93. package/docs/classes/hub_HubSimulate.HubSimulate.html +0 -75
  94. package/docs/classes/hub_HubTauri.HubTauri.html +0 -93
  95. package/docs/classes/hub_HubWebSocket.HubWebSocket.html +0 -112
  96. package/docs/documents/core_AutoCoreTagContext.AutoCoreTagContext.html +0 -148
  97. package/docs/enums/components_JogPanel.JogDistanceAction.html +0 -5
  98. package/docs/enums/components_JogPanel.JogPanelAction.html +0 -18
  99. package/docs/enums/components_JogPanel.JogSpeedAction.html +0 -5
  100. package/docs/enums/core_ActionMode.ActionMode.html +0 -6
  101. package/docs/enums/core_IndicatorColor.IndicatorColor.html +0 -23
  102. package/docs/functions/assets.BlocklyLogo.html +0 -1
  103. package/docs/functions/assets.Distance.html +0 -1
  104. package/docs/functions/assets.JogLong.html +0 -1
  105. package/docs/functions/assets.JogMedium.html +0 -1
  106. package/docs/functions/assets.JogShort.html +0 -1
  107. package/docs/functions/assets.PythonLogo.html +0 -1
  108. package/docs/functions/assets.Rotation3D.html +0 -1
  109. package/docs/functions/assets.RotationCcw.html +0 -1
  110. package/docs/functions/assets.RotationCcwA.html +0 -1
  111. package/docs/functions/assets.RotationCcwB.html +0 -1
  112. package/docs/functions/assets.RotationCcwC.html +0 -1
  113. package/docs/functions/assets.RotationCw.html +0 -1
  114. package/docs/functions/assets.RotationCwA.html +0 -1
  115. package/docs/functions/assets.RotationCwB.html +0 -1
  116. package/docs/functions/assets.RotationCwC.html +0 -1
  117. package/docs/functions/assets.Run.html +0 -1
  118. package/docs/functions/assets.Speed.html +0 -1
  119. package/docs/functions/assets.SpeedFast.html +0 -1
  120. package/docs/functions/assets.SpeedMedium.html +0 -1
  121. package/docs/functions/assets.SpeedNone.html +0 -1
  122. package/docs/functions/assets.SpeedSlow.html +0 -1
  123. package/docs/functions/assets.Walk.html +0 -1
  124. package/docs/functions/components_BlocklyEditor.createCustomToolbox.html +0 -6
  125. package/docs/functions/core_UniqueId.UniqueId.html +0 -9
  126. package/docs/functions/core_hoc.hocAddSubscription.html +0 -6
  127. package/docs/functions/hooks_adsHooks.useAdsRegisterSymbols.html +0 -16
  128. package/docs/functions/hooks_adsHooks.useAdsTapValue.html +0 -8
  129. package/docs/functions/hooks_adsHooks.useAdsWriteScaledValue.html +0 -18
  130. package/docs/functions/hooks_adsHooks.useAdsWriteValue.html +0 -9
  131. package/docs/functions/hooks_commandHooks.useRegisterSymbols.html +0 -16
  132. package/docs/functions/hooks_commandHooks.useTapValue.html +0 -10
  133. package/docs/functions/hooks_commandHooks.useWriteScaledValue.html +0 -18
  134. package/docs/functions/hooks_commandHooks.useWriteValue.html +0 -11
  135. package/docs/functions/hooks_useAutoCoreTag.ts.makeAutoCoreTagHooks.html +0 -12
  136. package/docs/functions/hooks_useScaledValue.useScaledValue.html +0 -18
  137. package/docs/functions/hub.createHub.html +0 -3
  138. package/docs/hierarchy.html +0 -1
  139. package/docs/index.html +0 -148
  140. package/docs/interfaces/components_IndicatorButton.IndicatorButtonProps.html +0 -654
  141. package/docs/interfaces/components_IndicatorRect.IndicatorRectProps.html +0 -37
  142. package/docs/interfaces/components_JogPanel.JogPanelButtonDefinition.html +0 -5
  143. package/docs/interfaces/components_ToggleGroup.ToggleGroupProps.html +0 -644
  144. package/docs/interfaces/core_AutoCoreTagTypes.BaseContextValue.html +0 -12
  145. package/docs/interfaces/core_AutoCoreTagTypes.ScaleConfig.html +0 -13
  146. package/docs/interfaces/core_EventEmitterContext.Action.html +0 -8
  147. package/docs/interfaces/core_EventEmitterContext.EventEmitterContextType.html +0 -33
  148. package/docs/interfaces/core_EventEmitterContext.State.html +0 -8
  149. package/docs/interfaces/core_EventEmitterContext.Subscription.html +0 -6
  150. package/docs/interfaces/core_IndicatorButtonState.IndicatorButtonState.html +0 -10
  151. package/docs/interfaces/core_PositionContext.IPositionContext.html +0 -17
  152. package/docs/interfaces/hub_CommandMessage.CommandMessage.html +0 -6
  153. package/docs/interfaces/hub_CommandMessage.CommandMessageResult.html +0 -4
  154. package/docs/modules/assets.html +0 -1
  155. package/docs/modules/assets_BlocklyLogo.html +0 -1
  156. package/docs/modules/assets_Distance.html +0 -1
  157. package/docs/modules/assets_JogLong.html +0 -1
  158. package/docs/modules/assets_JogMedium.html +0 -1
  159. package/docs/modules/assets_JogShort.html +0 -1
  160. package/docs/modules/assets_PythonLogo.html +0 -1
  161. package/docs/modules/assets_Rotation3D.html +0 -1
  162. package/docs/modules/assets_RotationCcw.html +0 -1
  163. package/docs/modules/assets_RotationCcwA.html +0 -1
  164. package/docs/modules/assets_RotationCcwB.html +0 -1
  165. package/docs/modules/assets_RotationCcwC.html +0 -1
  166. package/docs/modules/assets_RotationCw.html +0 -1
  167. package/docs/modules/assets_RotationCwA.html +0 -1
  168. package/docs/modules/assets_RotationCwB.html +0 -1
  169. package/docs/modules/assets_RotationCwC.html +0 -1
  170. package/docs/modules/assets_Run.html +0 -1
  171. package/docs/modules/assets_Speed.html +0 -1
  172. package/docs/modules/assets_SpeedFast.html +0 -1
  173. package/docs/modules/assets_SpeedMedium.html +0 -1
  174. package/docs/modules/assets_SpeedNone.html +0 -1
  175. package/docs/modules/assets_SpeedSlow.html +0 -1
  176. package/docs/modules/assets_Walk.html +0 -1
  177. package/docs/modules/components_AutoCoreDevPanel.html +0 -20
  178. package/docs/modules/components_BlocklyEditor.html +0 -1
  179. package/docs/modules/components_CodeEditor.html +0 -1
  180. package/docs/modules/components_FileList.html +0 -1
  181. package/docs/modules/components_FileSelect.html +0 -1
  182. package/docs/modules/components_FitText.html +0 -1
  183. package/docs/modules/components_Indicator.html +0 -1
  184. package/docs/modules/components_IndicatorButton.html +0 -1
  185. package/docs/modules/components_IndicatorRect.html +0 -1
  186. package/docs/modules/components_JogPanel.html +0 -1
  187. package/docs/modules/components_Lamp.html +0 -1
  188. package/docs/modules/components_Osk.html +0 -1
  189. package/docs/modules/components_OskDialog.html +0 -1
  190. package/docs/modules/components_ProgressBarWithValue.html +0 -1
  191. package/docs/modules/components_TextInput.html +0 -1
  192. package/docs/modules/components_ToggleGroup.html +0 -1
  193. package/docs/modules/components_ValueDisplay.html +0 -1
  194. package/docs/modules/components_ValueIndicator.html +0 -1
  195. package/docs/modules/components_ValueInput.html +0 -1
  196. package/docs/modules/core_ActionMode.html +0 -1
  197. package/docs/modules/core_AutoCoreTagContext.html +0 -11
  198. package/docs/modules/core_AutoCoreTagTypes.html +0 -1
  199. package/docs/modules/core_EventEmitterContext.html +0 -53
  200. package/docs/modules/core_IndicatorButtonState.html +0 -1
  201. package/docs/modules/core_IndicatorColor.html +0 -1
  202. package/docs/modules/core_MaskPatterns.html +0 -1
  203. package/docs/modules/core_NumerableTypes.html +0 -1
  204. package/docs/modules/core_PositionContext.html +0 -1
  205. package/docs/modules/core_UniqueId.html +0 -1
  206. package/docs/modules/core_ValueSimulator.html +0 -1
  207. package/docs/modules/core_hoc.html +0 -1
  208. package/docs/modules/hooks.html +0 -1
  209. package/docs/modules/hooks_adsHooks.html +0 -1
  210. package/docs/modules/hooks_commandHooks.html +0 -1
  211. package/docs/modules/hooks_useAutoCoreTag.ts.html +0 -52
  212. package/docs/modules/hooks_useScaledValue.html +0 -1
  213. package/docs/modules/hub.html +0 -1
  214. package/docs/modules/hub_CommandMessage.html +0 -1
  215. package/docs/modules/hub_HubBase.html +0 -1
  216. package/docs/modules/hub_HubSimulate.html +0 -1
  217. package/docs/modules/hub_HubTauri.html +0 -1
  218. package/docs/modules/hub_HubWebSocket.html +0 -1
  219. package/docs/modules.html +0 -23
  220. package/docs/types/components_IndicatorButton.IndicatorButtonOptionsType.html +0 -1
  221. package/docs/types/core_AutoCoreTagTypes.ExtractByTag.html +0 -2
  222. package/docs/types/core_AutoCoreTagTypes.PrimitiveKind.html +0 -1
  223. package/docs/types/core_AutoCoreTagTypes.TagConfig.html +0 -16
  224. package/docs/types/core_AutoCoreTagTypes.TagValueMap.html +0 -1
  225. package/docs/types/core_AutoCoreTagTypes.TagValueOf.html +0 -1
  226. package/docs/types/core_EventEmitterContext.EmitterDispatchFunction.html +0 -3
  227. package/docs/types/core_EventEmitterContext.EmitterSubscribeFunction.html +0 -3
  228. package/docs/types/core_EventEmitterContext.EmitterUnsubscribeFunction.html +0 -3
  229. package/docs/types/core_NumerableTypes.NumerableFormatOptions.html +0 -4
  230. package/docs/types/core_hoc.HocAddSubscriptionProps.html +0 -6
  231. package/docs/variables/components_AutoCoreDevPanel.AutoCoreDevPanel.html +0 -43
  232. package/docs/variables/components_BlocklyEditor.BlocklyEditor.html +0 -13
  233. package/docs/variables/components_BlocklyEditor.StandardToolbox.html +0 -1
  234. package/docs/variables/components_FileList.FileList.html +0 -23
  235. package/docs/variables/components_FileSelect.FileSelect.html +0 -1
  236. package/docs/variables/components_FitText.FitText.html +0 -4
  237. package/docs/variables/components_IndicatorButton.IndicatorButton.html +0 -1
  238. package/docs/variables/components_JogPanel.DefaultLinearJogButtons.html +0 -2
  239. package/docs/variables/components_JogPanel.DefaultRotationJogButtons.html +0 -2
  240. package/docs/variables/components_Osk.Osk.html +0 -1
  241. package/docs/variables/components_ProgressBarWithValue.ProgressBarWithValue.html +0 -1
  242. package/docs/variables/components_ToggleGroup.ToggleGroup.html +0 -1
  243. package/docs/variables/components_ValueInput.ValueInput.html +0 -4
  244. package/docs/variables/core_AutoCoreTagContext.AutoCoreTagContext.html +0 -1
  245. package/docs/variables/core_AutoCoreTagContext.AutoCoreTagProvider.html +0 -7
  246. package/docs/variables/core_EventEmitterContext.EventEmitterContext.html +0 -64
  247. package/docs/variables/core_EventEmitterContext.EventEmitterProvider.html +0 -10
  248. package/docs/variables/core_MaskPatterns.PrimeReactMaskPatterns.html +0 -14
  249. package/docs/variables/core_MaskPatterns.RegExMaskPatterns.html +0 -15
  250. package/docs/variables/core_PositionContext.DimensionsContext.html +0 -6
  251. package/docs/variables/hooks_useScaledValue.kMillimeters2Inches.html +0 -2
  252. package/docs/variables/hooks_useScaledValue.kNewtons2Pounds.html +0 -2
@@ -3,99 +3,56 @@
3
3
  * Created Date: 2023-12-15 14:21:33
4
4
  * Author: Thomas C. Bitsky Jr.
5
5
  * -----
6
- * Last Modified: 2025-09-05 14:50:03
6
+ * Last Modified: 2026-01-29 09:34:10
7
7
  * Modified By: ADC
8
8
  * -----
9
- *
9
+ *
10
10
  */
11
11
 
12
- import type { EventEmitterContextType} from '../core/EventEmitterContext';
13
- import type {CommandMessageResult} from "./CommandMessage";
12
+ import type { EventEmitterContextType } from '../core/EventEmitterContext';
13
+ import type { CommandMessage } from "./CommandMessage";
14
+ import { MessageType } from "./CommandMessage";
14
15
 
15
16
 
16
17
  /**
17
- * Base class for the interface for the IPC to the backend,
18
- * which may be websockets, MQTT, the Tauri API,
19
- * or something else.
20
- *
21
- * The EventEmitterContext should generate the hub automatically.
22
- *
23
- * # Usage
24
- * The hub can be used to publish and subscribe to
25
- * topics in the front-end, regardless of being connected to any backend.
26
- *
27
- * ```
28
- * const {dispatch, subscribe, unsubscribe} = useContext(EventEmitterContext);
29
- * const [controlPower, setControlPower] = useState(false);
30
- * useEffect(() => {
31
- * const unsubscribeControlPower = subscribe('value-simulator-bBit1', (value) => {
32
- * setControlPower(value);
33
- * });
34
- *
35
- *
36
- * return () => {
37
- * unsubscribe(unsubscribeControlPower);
38
- * }
39
- * }, [] );
18
+ * @class HubBase
19
+ * @abstract
40
20
  *
41
- * const onPbPressed = () => {
42
- * let count = 1;
43
- * dispatch({
44
- * topic: "my-awesome-topic",
45
- * payload: count
46
- * });
47
- * }
21
+ * Abstract base class that defines the interface for communicating with the AutoCore backend.
22
+ * Implementations (like `HubWebSocket` or `HubTauri`) handle the specific transport mechanics.
48
23
  *
49
- * ```
50
- * The hub should also be used for invoking events in the backend.
51
- * This example will call the function "update_count" in the backend, passing
52
- * the expected argument "count". Details of the interaction between the Hub and
53
- * the backend will be handled by the appropriate HubBase sub-class, and should
54
- * be transparent to the front end.
55
- *
56
- * ```
57
- * const {invoke} = useContext(EventEmitterContext);
58
- * const incrementCount = () => {
59
- * count += 1;
60
- * invoke('update_count', {"count": count});
61
- * };
24
+ * ## Core Responsibilities
62
25
  *
63
- * Subscribing to a topic is simple. The type of value received is specific
64
- * to the topic.
26
+ * 1. **Transport Abstraction**: Provides a unified API (`read`, `write`, `subscribe`) regardless of
27
+ * underlying transport (WS, IPC, etc.).
28
+ * 2. **Topic Mapping**: Maintains a bidirectional mapping between local `tagName` (UI friendly)
29
+ * and backend `FQDN` (Fully Qualified Domain Name).
30
+ * - `tagName`: "motorsEnable"
31
+ * - `FQDN`: "ADS.Main.bMotorsEnable"
32
+ * 3. **Event Dispatching**: Routes incoming messages from the backend to the `EventEmitterContext`.
65
33
  *
66
- * Example: Listen to an event 'xarm-position':
67
- * ```
68
- * const {subscribe, unsubscribe} = useContext(EventEmitterContext);
69
- * useEffect(() => {
70
- * const unsubscripeMp = subscribe('xarm-position', (value) => {
71
- * // The publisher sent a JSON object of 3D position values.
72
- * setX(value.x);
73
- * setY(value.y);
74
- * setZ(value.z);
75
- * setA(value.roll);
76
- * setB(value.yaw);
77
- * setC(value.pitch);
78
- * });
34
+ * ## Usage
79
35
  *
80
- * return () => {
81
- * unsubscribe(unsubscripeMp);
82
- * }
36
+ * The `Hub` is typically accessed via the `EventEmitterContext`:
83
37
  *
84
- * }, [] );
85
- *
38
+ * ```typescript
39
+ * const { hub } = useContext(EventEmitterContext);
40
+ * await hub.write("ADS.Main.nSpeed", 500);
86
41
  * ```
87
- *
88
42
  */
89
43
  export abstract class HubBase {
90
44
 
91
- protected localTopicToBackendTopicMap : Map<string,string> = new Map<string,string>();
92
- protected backendTopicToLocalMap : Map<string,string> = new Map<string,string>();
93
- protected localFNameToBackendFNameMap : Map<string,string> = new Map<string,string>();
94
- protected backendFNameToLocalFNameMap : Map<string,string> = new Map<string,string>();
45
+ /** Maps local tag names to backend FQDNs. */
46
+ protected localTopicToBackendTopicMap: Map<string, string> = new Map<string, string>();
47
+
48
+ /** Maps backend FQDNs to local tag names. */
49
+ protected backendTopicToLocalMap: Map<string, string> = new Map<string, string>();
95
50
 
96
- protected context : EventEmitterContextType | null = null;
51
+ /** Reference to the global event emitter for dispatching incoming messages. */
52
+ protected context: EventEmitterContextType | null = null;
97
53
 
98
- protected isConnected_ : boolean = false;
54
+ /** Connection state tracker. */
55
+ protected isConnected_: boolean = false;
99
56
 
100
57
 
101
58
  /**
@@ -106,66 +63,125 @@ export abstract class HubBase {
106
63
 
107
64
 
108
65
  /**
109
- * Set the EventEmitterContext for this instance of the Hub. The EventEmitterContext
110
- * should handle this as part of the initialization sequence. Because React can
111
- * sometimes make (and destroy) multiple copies of the EventEmitterContext, it's important
112
- * that the context be stored in the instance this way so that the HubBase can properly target
113
- * right context.
66
+ * Links this Hub instance with the React application's Event Context.
114
67
  *
115
- * If this context is not sent, no events will be emitted from the backend to the front end,
116
- * and global events in the interface may not work.
68
+ * This connection allows the Hub to "push" messages into the React app by calling `context.dispatch()`.
69
+ * This is called automatically by `EventEmitterProvider` on initialization.
117
70
  *
71
+ * @param context The React context instance.
118
72
  */
119
- setContext(context : EventEmitterContextType | null ) {
73
+ setContext(context: EventEmitterContextType | null) {
120
74
  this.context = context;
121
- }
75
+ }
122
76
 
123
- /**
124
- * Invoke/send a message to the back end.
125
- * This does NOT get published to the front end.
77
+ // =========================================================================
78
+ // Abstract Methods - Must be implemented by subclasses
79
+ // =========================================================================
80
+
81
+ /**
82
+ * Sends a raw command message to the backend.
83
+ *
84
+ * @param topic The resource identifier (FQDN).
85
+ * @param messageType The operation to perform (Read, Write, etc.).
86
+ * @param payload The data payload.
87
+ * @returns A Promise that resolves with the server's response.
126
88
  */
127
- abstract invoke(domain: string, fname: string, payload? : object) : Promise<CommandMessageResult>;
89
+ abstract invoke(topic: string, messageType: MessageType, payload?: object): Promise<CommandMessage>;
128
90
 
91
+ // =========================================================================
92
+ // Convenience Helper Methods
93
+ // =========================================================================
129
94
 
130
95
  /**
131
- * Allos the derived class to set whether the hub is connected to its source.
132
- * @param s boolean
96
+ * Request the current value of a resource.
97
+ *
98
+ * @param topic FQDN of the resource.
133
99
  */
134
- protected setIsConnected = (s : boolean) => {
135
- this.isConnected_ = s;
100
+ read(topic: string, payload?: object): Promise<CommandMessage> {
101
+ return this.invoke(topic, MessageType.Read, payload);
136
102
  }
137
103
 
138
104
  /**
139
- * Returns true if the Hub is connected to its source.
105
+ * Write a new value to a resource.
106
+ *
107
+ * @param topic FQDN of the resource.
108
+ * @param value The value to write.
140
109
  */
141
- isConnected = () : boolean => {
142
- return this.isConnected_;
110
+ write(topic: string, value: any): Promise<CommandMessage> {
111
+ return this.invoke(topic, MessageType.Write, { value });
112
+ }
113
+
114
+ /**
115
+ * Subscribe to updates for a specific resource.
116
+ *
117
+ * Registers a mapping so that when the server sends updates for `topic` (FQDN),
118
+ * the Hub will translate it to `tagName` before dispatching to the UI.
119
+ *
120
+ * @param tagName The local alias for this resource (e.g., "position").
121
+ * @param topic The backend FQDN (e.g., "ADS.Main.fPos").
122
+ * @param payload Optional subscription parameters (rate, deadband).
123
+ */
124
+ subscribe(tagName : string, topic: string, payload?: object): Promise<CommandMessage> {
125
+ this.mapTopic(tagName, topic);
126
+ return this.invoke(topic, MessageType.Subscribe, payload);
127
+ }
128
+
129
+ /**
130
+ * Unsubscribe from updates.
131
+ *
132
+ * Uses the `tagName` to look up the FQDN and send the unsubscribe command.
133
+ * Also removes the local mapping.
134
+ *
135
+ * @param tagName The local alias to unsubscribe.
136
+ */
137
+ unsubscribe( /* topic: string,*/ tagName : string, payload?: object): Promise<CommandMessage> {
138
+ const fqdn = this.toBackendTopic(tagName);
139
+ this.unmapTopic(tagName);
140
+ return this.invoke(fqdn, MessageType.Unsubscribe, payload);
141
+ }
142
+
143
+ /**
144
+ * Send a generic request (custom command).
145
+ */
146
+ request(topic: string, payload?: object): Promise<CommandMessage> {
147
+ return this.invoke(topic, MessageType.Request, payload);
148
+ }
149
+
150
+ // =========================================================================
151
+ // Connection State
152
+ // =========================================================================
153
+
154
+ /**
155
+ * Update internal connection state.
156
+ */
157
+ protected setIsConnected = (s: boolean) => {
158
+ this.isConnected_ = s;
143
159
  }
144
160
 
145
161
  /**
146
- * Convenience function to invoke a command with an optional topic and optional value.
147
- * This will invoke the specified command in the backend. It does not broadcast the
148
- * value within the local frontend.
149
- * @param domain string The domain of the command that will be invoked.
150
- * @param fname string Function name
151
- * @param topic string Topic
152
- * @param value any data payload
162
+ * Check if currently connected to backend.
153
163
  */
154
- invokeTopic( domain: string, fname : string, topic : string | null, value? : any ) : Promise<CommandMessageResult> {
155
- const msg = {
156
- topic : topic,
157
- data : value
158
- };
159
- return this.invoke(domain, fname, msg);
164
+ isConnected = (): boolean => {
165
+ return this.isConnected_;
160
166
  }
161
167
 
162
- /**
163
- * Pubish a topic throughout the web app using the
164
- * Global EventEmitterContext. This will broadcast within the local frontend.
165
- * This does NOT get relayed to the backend.
168
+ // =========================================================================
169
+ // Frontend Event Bus (Local Publish/Subscribe)
170
+ // =========================================================================
171
+
172
+ /**
173
+ * Dispatches an event to the React application.
174
+ *
175
+ * 1. Translates the `topic` (potentially an FQDN) to a local `tagName` if a mapping exists.
176
+ * 2. Calls `context.dispatch()` to notify local subscribers.
177
+ *
178
+ * This is the bridge between the backend transport and the frontend UI components.
179
+ *
180
+ * @param topic The topic from the message (usually FQDN).
181
+ * @param data The data payload.
166
182
  */
167
- publish(topic : string, data : any | undefined) : void {
168
- const convertedTopic = this.toLocalTopic(topic);
183
+ publish(topic: string, data: any | undefined): void {
184
+ const convertedTopic = this.toLocalTopic(topic);
169
185
 
170
186
  console.log(`HUB Dispatch topic ${convertedTopic} payload ${JSON.stringify(data)}`);
171
187
  this.context?.dispatch({
@@ -174,139 +190,47 @@ export abstract class HubBase {
174
190
  });
175
191
  }
176
192
 
193
+ // =========================================================================
194
+ // Topic Mapping (for aliasing backend topics to local names)
195
+ // =========================================================================
177
196
 
178
197
  /**
179
- * Map a local topic to a topic in the backend.
180
- * @param localTopic string
181
- * @param backendTopic string
198
+ * Registers a mapping between a local name and a backend FQDN.
182
199
  */
183
- mapTopic(localTopic : string, backendTopic: string ) : void {
200
+ mapTopic(localTopic: string, backendTopic: string): void {
184
201
  this.localTopicToBackendTopicMap.set(localTopic, backendTopic);
185
202
  this.backendTopicToLocalMap.set(backendTopic, localTopic);
186
203
  }
187
204
 
188
205
  /**
189
- * Unmap a local topic.
190
- * @param localTopic string
206
+ * Removes a mapping.
191
207
  */
192
- unmapTopic(localTopic: string) : void {
193
- if (this.localTopicToBackendTopicMap.has(localTopic) ) {
208
+ unmapTopic(localTopic: string): void {
209
+ if (this.localTopicToBackendTopicMap.has(localTopic)) {
194
210
  const be = this.localTopicToBackendTopicMap.get(localTopic);
195
211
  this.localTopicToBackendTopicMap.delete(localTopic);
196
-
212
+
197
213
  if (be !== null && be !== undefined && this.backendTopicToLocalMap.has(be)) {
198
214
  this.backendTopicToLocalMap.delete(be);
199
215
  }
200
- }
216
+ }
201
217
  }
202
218
 
203
-
204
219
  /**
205
- * Map a local function name, as would be sent to the invoke method, to a
206
- * function name in the backend.
207
- * @param localFName string
208
- * @param backendFName string
220
+ * Translates Local Name -> Backend FQDN.
209
221
  */
210
- mapFName(localFName : string, backendFName: string ) : void {
211
- this.localFNameToBackendFNameMap.set(localFName, backendFName);
212
- this.backendFNameToLocalFNameMap.set(backendFName, localFName);
222
+ toBackendTopic(localTopic: string): string {
223
+ const mapped = this.localTopicToBackendTopicMap.get(localTopic);
224
+ return mapped ?? localTopic;
213
225
  }
214
226
 
215
227
  /**
216
- * Unmap a local function name.
217
- * @param localFName string
228
+ * Translates Backend FQDN -> Local Name.
218
229
  */
219
- unmapFName(localFName: string) : void {
220
- if (this.localFNameToBackendFNameMap.has(localFName) ) {
221
- const be = this.localFNameToBackendFNameMap.get(localFName);
222
- this.localFNameToBackendFNameMap.delete(localFName);
223
-
224
- if (be !== null && be !== undefined && this.backendFNameToLocalFNameMap.has(be)) {
225
- this.backendFNameToLocalFNameMap.delete(be);
226
- }
227
- }
230
+ toLocalTopic(backendTopic: string): string {
231
+ const mapped = this.backendTopicToLocalMap.get(backendTopic);
232
+ return mapped ?? backendTopic;
228
233
  }
229
-
230
-
231
- /**
232
- * Convert a local topic to a backend topic. If a mapping isn't
233
- * registered, the local topic is returned.
234
- * @param localTopic local topic name
235
- * @returns string
236
- */
237
- toBackendTopic(localTopic : string) : string {
238
- if (this.localTopicToBackendTopicMap.has(localTopic) ) {
239
- const ret = this.localTopicToBackendTopicMap.get(localTopic);
240
- if (ret !== null && ret !== undefined)
241
- return ret;
242
- else
243
- return localTopic;
244
- }
245
- else {
246
- return localTopic;
247
- }
248
- }
249
-
250
- /**
251
- * Convert a local function name to a backend function name. If a mapping isn't
252
- * registered, the local FName is returned.
253
- * @param localTopic local function name
254
- * @returns string
255
- */
256
- toBackendFName(localFName : string) : string {
257
- if (this.localFNameToBackendFNameMap.has(localFName) ) {
258
- const ret = this.localFNameToBackendFNameMap.get(localFName);
259
- if (ret !== null && ret !== undefined)
260
- return ret;
261
- else
262
- return localFName;
263
- }
264
- else {
265
- return localFName;
266
- }
267
- }
268
-
269
-
270
- /**
271
- * Convert a backend topic to a local topic. If a mapping isn't
272
- * registered, the backend topic is returned.
273
- * @param backendTopic backend topic name
274
- * @returns string
275
- */
276
- toLocalTopic(backendTopic : string) : string {
277
- if (this.backendTopicToLocalMap.has(backendTopic) ) {
278
- const ret = this.backendTopicToLocalMap.get(backendTopic);
279
- if (ret !== null && ret !== undefined)
280
- return ret;
281
- else
282
- return backendTopic;
283
- }
284
- else {
285
- return backendTopic;
286
- }
287
- }
288
-
289
-
290
- /**
291
- * Convert a backend function name to a local function name. If a mapping isn't
292
- * registered, the backend function name is returned.
293
- * @param backendTopic backend function name
294
- * @returns string
295
- */
296
- toLocalFName(backendTopic : string) : string {
297
- if (this.backendFNameToLocalFNameMap.has(backendTopic) ) {
298
- const ret = this.backendFNameToLocalFNameMap.get(backendTopic);
299
- if (ret !== null && ret !== undefined)
300
- return ret;
301
- else
302
- return backendTopic;
303
- }
304
- else {
305
- return backendTopic;
306
- }
307
- }
308
-
309
-
310
234
  }
311
235
 
312
236
 
@@ -2,54 +2,123 @@
2
2
  * Copyright (C) 2023 Automated Design Corp. All Rights Reserved.
3
3
  * Created Date: 2023-12-17 10:38:21
4
4
  * -----
5
- * Last Modified: 2025-09-05 14:49:57
5
+ * Last Modified: 2026-01-29 09:34:15
6
6
  * Modified By: ADC
7
7
  * -----
8
- *
8
+ *
9
9
  */
10
10
 
11
-
12
11
  import { HubBase } from './HubBase';
13
- import type { CommandMessageResult } from "./CommandMessage";
12
+ import type { CommandMessage } from "./CommandMessage";
13
+ import { MessageType } from "./CommandMessage";
14
+
14
15
  /**
15
- * Hub for simulating functionality when no backend is present.
16
+ * Hub for simulating backend functionality when no actual backend is present.
17
+ *
18
+ * Useful for development, testing, and demos without a running autocore-server.
19
+ * The simulator echoes back requests as successful responses after a configurable delay.
20
+ *
21
+ * ## Usage Examples
22
+ *
23
+ * ```typescript
24
+ * const { hub } = useContext(EventEmitterContext);
25
+ *
26
+ * // Read returns the topic as the "value"
27
+ * const result = await hub.read("ads.plc1.gio.bControlPowerOk");
28
+ * console.log(result.data); // { value: "ads.plc1.gio.bControlPowerOk" }
29
+ *
30
+ * // Write echoes back the written value
31
+ * await hub.write("ads.plc1.gio.nSetpoint", 100);
32
+ * ```
16
33
  */
17
34
  export class HubSimulate extends HubBase {
18
35
 
36
+ private responseDelay: number;
37
+
19
38
  /**
20
39
  * Constructor
40
+ * @param responseDelay Simulated response delay in milliseconds (default: 20ms)
21
41
  */
22
- constructor() {
42
+ constructor(responseDelay: number = 20) {
23
43
  super();
44
+ this.responseDelay = responseDelay;
45
+ this.setIsConnected(true); // Simulator is always "connected"
24
46
  }
25
47
 
26
48
  /**
27
- * Invoke a method in the Socket.IO backend and wait for acknowledgment.
28
- *
29
- * @param fname method name
49
+ * Simulate sending a message to a backend.
50
+ *
51
+ * For Read operations, returns the topic as the value.
52
+ * For Write operations, echoes back the payload.
53
+ * For all operations, returns a successful response after the configured delay.
54
+ *
55
+ * @param topic The FQDN of the resource
56
+ * @param messageType The action to perform
30
57
  * @param payload Optional data payload
31
- * @param timeout Timeout in milliseconds after which the promise is rejected if no response is received.
32
- * @returns A Promise that resolves to the response from the backend or rejects if a timeout occurs.
58
+ * @returns Promise<CommandMessage> A simulated successful response
33
59
  */
34
- invoke(domain: string, fname: string, payload?: object, timeout: number = 20): Promise<CommandMessageResult> {
35
- domain; // Not using for simulator
36
- fname; // Not using for simulator
37
- return new Promise((resolve, reject) => {
38
- reject; // not using for simulator
39
- // Set a timeout to echo a response
60
+ invoke(topic: string, messageType: MessageType, payload?: object): Promise<CommandMessage> {
61
+ return new Promise((resolve) => {
40
62
  setTimeout(() => {
63
+ let responseData: any;
64
+
65
+ // Simulate appropriate responses based on message type
66
+ switch (messageType) {
67
+ case MessageType.Read:
68
+ // Simulate reading - return the topic as a "value"
69
+ responseData = { value: topic, simulated: true };
70
+ break;
71
+
72
+ case MessageType.Write:
73
+ // Simulate writing - echo back the payload
74
+ responseData = { written: true, ...payload };
75
+ break;
76
+
77
+ case MessageType.Subscribe:
78
+ // Simulate subscribing - acknowledge
79
+ responseData = { subscribed: true, topic: topic };
80
+ break;
41
81
 
42
- let ret: CommandMessageResult = {
43
- data: payload,
44
- error_message: "",
45
- success: true
82
+ case MessageType.Unsubscribe:
83
+ // Simulate unsubscribing - acknowledge
84
+ responseData = { unsubscribed: true, topic: topic };
85
+ break;
86
+
87
+ default:
88
+ // Echo back the payload for other message types
89
+ responseData = payload ?? {};
90
+ break;
91
+ }
92
+
93
+ const response: CommandMessage = {
94
+ transaction_id: 0,
95
+ timecode: Date.now(),
96
+ topic: topic,
97
+ message_type: MessageType.Response,
98
+ data: responseData,
99
+ success: true,
100
+ error_message: ''
46
101
  };
47
102
 
48
- resolve(ret);
49
- }, timeout);
103
+ resolve(response);
104
+ }, this.responseDelay);
50
105
  });
51
106
  }
52
107
 
108
+ /**
109
+ * Simulate a broadcast from the "backend".
110
+ *
111
+ * This is useful for testing subscription handlers.
112
+ *
113
+ * @param topic The topic to broadcast on
114
+ * @param data The data to broadcast
115
+ * @param delay Optional delay before broadcasting (default: 0ms)
116
+ */
117
+ simulateBroadcast(topic: string, data: any, delay: number = 0): void {
118
+ setTimeout(() => {
119
+ this.publish(topic, data);
120
+ }, delay);
121
+ }
53
122
  }
54
123
 
55
- export default HubSimulate;
124
+ export default HubSimulate;