@adcops/autocore-react 3.0.39 → 3.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/additional-docs/AutoCoreTagContext.md +441 -0
- package/dist/assets/BlocklyLogo.d.ts +1 -0
- package/dist/assets/BlocklyLogo.d.ts.map +1 -0
- package/dist/assets/Distance.d.ts +1 -0
- package/dist/assets/Distance.d.ts.map +1 -0
- package/dist/assets/JogLong.d.ts +1 -0
- package/dist/assets/JogLong.d.ts.map +1 -0
- package/dist/assets/JogMedium.d.ts +1 -0
- package/dist/assets/JogMedium.d.ts.map +1 -0
- package/dist/assets/JogShort.d.ts +1 -0
- package/dist/assets/JogShort.d.ts.map +1 -0
- package/dist/assets/PythonLogo.d.ts +1 -0
- package/dist/assets/PythonLogo.d.ts.map +1 -0
- package/dist/assets/Rotation3D.d.ts +1 -0
- package/dist/assets/Rotation3D.d.ts.map +1 -0
- package/dist/assets/RotationCcw.d.ts +1 -0
- package/dist/assets/RotationCcw.d.ts.map +1 -0
- package/dist/assets/RotationCcwA.d.ts +1 -0
- package/dist/assets/RotationCcwA.d.ts.map +1 -0
- package/dist/assets/RotationCcwB.d.ts +1 -0
- package/dist/assets/RotationCcwB.d.ts.map +1 -0
- package/dist/assets/RotationCcwC.d.ts +1 -0
- package/dist/assets/RotationCcwC.d.ts.map +1 -0
- package/dist/assets/RotationCw.d.ts +1 -0
- package/dist/assets/RotationCw.d.ts.map +1 -0
- package/dist/assets/RotationCwA.d.ts +1 -0
- package/dist/assets/RotationCwA.d.ts.map +1 -0
- package/dist/assets/RotationCwB.d.ts +1 -0
- package/dist/assets/RotationCwB.d.ts.map +1 -0
- package/dist/assets/RotationCwC.d.ts +1 -0
- package/dist/assets/RotationCwC.d.ts.map +1 -0
- package/dist/assets/Run.d.ts +1 -0
- package/dist/assets/Run.d.ts.map +1 -0
- package/dist/assets/Speed.d.ts +1 -0
- package/dist/assets/Speed.d.ts.map +1 -0
- package/dist/assets/SpeedFast.d.ts +1 -0
- package/dist/assets/SpeedFast.d.ts.map +1 -0
- package/dist/assets/SpeedMedium.d.ts +1 -0
- package/dist/assets/SpeedMedium.d.ts.map +1 -0
- package/dist/assets/SpeedNone.d.ts +1 -0
- package/dist/assets/SpeedNone.d.ts.map +1 -0
- package/dist/assets/SpeedSlow.d.ts +1 -0
- package/dist/assets/SpeedSlow.d.ts.map +1 -0
- package/dist/assets/Walk.d.ts +1 -0
- package/dist/assets/Walk.d.ts.map +1 -0
- package/dist/assets/index.d.ts +1 -0
- package/dist/assets/index.d.ts.map +1 -0
- package/dist/components/AutoCoreDevPanel.d.ts +144 -0
- package/dist/components/AutoCoreDevPanel.d.ts.map +1 -0
- package/dist/components/AutoCoreDevPanel.js +1 -0
- package/dist/components/BlocklyEditor.d.ts +1 -0
- package/dist/components/BlocklyEditor.d.ts.map +1 -0
- package/dist/components/BlocklyEditor.js +1 -1
- package/dist/components/CodeEditor.d.ts +2 -1
- package/dist/components/CodeEditor.d.ts.map +1 -0
- package/dist/components/CodeEditor.js +1 -1
- package/dist/components/FileList.d.ts +1 -0
- package/dist/components/FileList.d.ts.map +1 -0
- package/dist/components/FileList.js +1 -1
- package/dist/components/FileSelect.d.ts +1 -0
- package/dist/components/FileSelect.d.ts.map +1 -0
- package/dist/components/FileSelect.js +1 -1
- package/dist/components/FitText.d.ts +1 -0
- package/dist/components/FitText.d.ts.map +1 -0
- package/dist/components/FitText.js +1 -1
- package/dist/components/Indicator.d.ts +2 -1
- package/dist/components/Indicator.d.ts.map +1 -0
- package/dist/components/Indicator.js +1 -1
- package/dist/components/IndicatorButton.d.ts +23 -137
- package/dist/components/IndicatorButton.d.ts.map +1 -0
- package/dist/components/IndicatorButton.js +1 -1
- package/dist/components/IndicatorRect.d.ts +2 -1
- package/dist/components/IndicatorRect.d.ts.map +1 -0
- package/dist/components/JogPanel.d.ts +1 -0
- package/dist/components/JogPanel.d.ts.map +1 -0
- package/dist/components/Lamp.d.ts +2 -1
- package/dist/components/Lamp.d.ts.map +1 -0
- package/dist/components/Lamp.js +1 -1
- package/dist/components/Osk.d.ts +1 -0
- package/dist/components/Osk.d.ts.map +1 -0
- package/dist/components/Osk.js +1 -1
- package/dist/components/OskDialog.d.ts +1 -0
- package/dist/components/OskDialog.d.ts.map +1 -0
- package/dist/components/ProgressBarWithValue.d.ts +1 -0
- package/dist/components/ProgressBarWithValue.d.ts.map +1 -0
- package/dist/components/ProgressBarWithValue.js +1 -1
- package/dist/components/TextInput.d.ts +62 -103
- package/dist/components/TextInput.d.ts.map +1 -0
- package/dist/components/TextInput.js +1 -1
- package/dist/components/ToggleGroup.d.ts +2 -1
- package/dist/components/ToggleGroup.d.ts.map +1 -0
- package/dist/components/ToggleGroup.js +1 -1
- package/dist/components/ValueDisplay.d.ts +3 -2
- package/dist/components/ValueDisplay.d.ts.map +1 -0
- package/dist/components/ValueDisplay.js +1 -1
- package/dist/components/ValueIndicator.d.ts +2 -1
- package/dist/components/ValueIndicator.d.ts.map +1 -0
- package/dist/components/ValueIndicator.js +1 -1
- package/dist/components/ValueInput.d.ts +2 -1
- package/dist/components/ValueInput.d.ts.map +1 -0
- package/dist/components/ValueInput.js +1 -1
- package/dist/core/ActionMode.d.ts +1 -0
- package/dist/core/ActionMode.d.ts.map +1 -0
- package/dist/core/AutoCoreTagContext.d.ts +224 -0
- package/dist/core/AutoCoreTagContext.d.ts.map +1 -0
- package/dist/core/AutoCoreTagContext.js +1 -0
- package/dist/core/AutoCoreTagTypes.d.ts +162 -0
- package/dist/core/AutoCoreTagTypes.d.ts.map +1 -0
- package/dist/core/AutoCoreTagTypes.js +1 -0
- package/dist/core/EventEmitterContext.d.ts +295 -2
- package/dist/core/EventEmitterContext.d.ts.map +1 -0
- package/dist/core/EventEmitterContext.js +1 -1
- package/dist/core/IndicatorButtonState.d.ts +1 -0
- package/dist/core/IndicatorButtonState.d.ts.map +1 -0
- package/dist/core/IndicatorColor.d.ts +1 -0
- package/dist/core/IndicatorColor.d.ts.map +1 -0
- package/dist/core/MaskPatterns.d.ts +1 -0
- package/dist/core/MaskPatterns.d.ts.map +1 -0
- package/dist/core/NumerableTypes.d.ts +1 -0
- package/dist/core/NumerableTypes.d.ts.map +1 -0
- package/dist/core/NumerableTypes.js +1 -1
- package/dist/core/PositionContext.d.ts +1 -1
- package/dist/core/PositionContext.d.ts.map +1 -0
- package/dist/core/UniqueId.d.ts +1 -0
- package/dist/core/UniqueId.d.ts.map +1 -0
- package/dist/core/ValueSimulator.d.ts +2 -1
- package/dist/core/ValueSimulator.d.ts.map +1 -0
- package/dist/core/ValueSimulator.js +1 -1
- package/dist/core/hoc.d.ts +1 -0
- package/dist/core/hoc.d.ts.map +1 -0
- package/dist/core/hoc.js +1 -1
- package/dist/hooks/adsHooks.d.ts +1 -0
- package/dist/hooks/adsHooks.d.ts.map +1 -0
- package/dist/hooks/adsHooks.js +1 -1
- package/dist/hooks/commandHooks.d.ts +1 -0
- package/dist/hooks/commandHooks.d.ts.map +1 -0
- package/dist/hooks/commandHooks.js +1 -1
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/useAutoCoreTag.d.ts +26 -0
- package/dist/hooks/useAutoCoreTag.d.ts.map +1 -0
- package/dist/hooks/useAutoCoreTag.js +1 -0
- package/dist/hooks/useScaledValue.d.ts +1 -0
- package/dist/hooks/useScaledValue.d.ts.map +1 -0
- package/dist/hooks/useScaledValue.js +1 -1
- package/dist/hub/CommandMessage.d.ts +1 -0
- package/dist/hub/CommandMessage.d.ts.map +1 -0
- package/dist/hub/HubBase.d.ts +3 -2
- package/dist/hub/HubBase.d.ts.map +1 -0
- package/dist/hub/HubSimulate.d.ts +2 -1
- package/dist/hub/HubSimulate.d.ts.map +1 -0
- package/dist/hub/HubSimulate.js +1 -1
- package/dist/hub/HubTauri.d.ts +2 -1
- package/dist/hub/HubTauri.d.ts.map +1 -0
- package/dist/hub/HubTauri.js +1 -1
- package/dist/hub/HubWebSocket.d.ts +2 -1
- package/dist/hub/HubWebSocket.d.ts.map +1 -0
- package/dist/hub/HubWebSocket.js +1 -1
- package/dist/hub/index.d.ts +2 -1
- package/dist/hub/index.d.ts.map +1 -0
- package/dist/hub/index.js +1 -1
- package/docs/.nojekyll +1 -0
- package/docs/assets/hierarchy.js +1 -0
- package/docs/assets/highlight.css +134 -0
- package/docs/assets/icons.js +18 -0
- package/docs/assets/icons.svg +1 -0
- package/docs/assets/main.js +60 -0
- package/docs/assets/navigation.js +1 -0
- package/docs/assets/search.js +1 -0
- package/docs/assets/style.css +1633 -0
- package/docs/classes/components_CodeEditor.CodeEditor.html +108 -101
- package/docs/classes/components_Indicator.Indicator.html +122 -0
- package/docs/classes/components_IndicatorRect.IndicatorRect.html +121 -0
- package/docs/classes/components_JogPanel.JogPanel.html +104 -106
- package/docs/classes/components_Lamp.Lamp.html +96 -79
- package/docs/classes/components_OskDialog.OskDialog.html +125 -0
- package/docs/classes/components_TextInput.TextInput.html +99 -89
- package/docs/classes/components_ValueDisplay.ValueDisplay.html +148 -0
- package/docs/classes/components_ValueIndicator.ValueIndicator.html +98 -91
- package/docs/classes/core_ValueSimulator.ValueSimulator.html +51 -0
- package/docs/classes/hub_HubBase.HubBase.html +106 -0
- package/docs/classes/hub_HubSimulate.HubSimulate.html +75 -0
- package/docs/classes/hub_HubTauri.HubTauri.html +93 -0
- package/docs/classes/hub_HubWebSocket.HubWebSocket.html +75 -69
- package/docs/documents/core_AutoCoreTagContext.AutoCoreTagContext.html +148 -0
- package/docs/enums/components_JogPanel.JogDistanceAction.html +5 -5
- package/docs/enums/components_JogPanel.JogPanelAction.html +18 -18
- package/docs/enums/components_JogPanel.JogSpeedAction.html +5 -5
- package/docs/enums/core_ActionMode.ActionMode.html +6 -6
- package/docs/enums/core_IndicatorColor.IndicatorColor.html +22 -22
- package/docs/functions/assets.BlocklyLogo.html +1 -0
- package/docs/functions/assets.Distance.html +1 -0
- package/docs/functions/assets.JogLong.html +1 -0
- package/docs/functions/assets.JogMedium.html +1 -0
- package/docs/functions/assets.JogShort.html +1 -0
- package/docs/functions/assets.PythonLogo.html +1 -0
- package/docs/functions/assets.Rotation3D.html +1 -0
- package/docs/functions/assets.RotationCcw.html +1 -0
- package/docs/functions/assets.RotationCcwA.html +1 -0
- package/docs/functions/assets.RotationCcwB.html +1 -0
- package/docs/functions/assets.RotationCcwC.html +1 -0
- package/docs/functions/assets.RotationCw.html +1 -0
- package/docs/functions/assets.RotationCwA.html +1 -0
- package/docs/functions/assets.RotationCwB.html +1 -0
- package/docs/functions/assets.RotationCwC.html +1 -0
- package/docs/functions/assets.Run.html +1 -0
- package/docs/functions/assets.Speed.html +1 -0
- package/docs/functions/assets.SpeedFast.html +1 -0
- package/docs/functions/assets.SpeedMedium.html +1 -0
- package/docs/functions/assets.SpeedNone.html +1 -0
- package/docs/functions/assets.SpeedSlow.html +1 -0
- package/docs/functions/assets.Walk.html +1 -0
- package/docs/functions/components_BlocklyEditor.createCustomToolbox.html +5 -5
- package/docs/functions/core_UniqueId.UniqueId.html +9 -0
- package/docs/functions/core_hoc.hocAddSubscription.html +6 -0
- package/docs/functions/hooks_adsHooks.useAdsRegisterSymbols.html +16 -0
- package/docs/functions/hooks_adsHooks.useAdsTapValue.html +8 -0
- package/docs/functions/hooks_adsHooks.useAdsWriteScaledValue.html +18 -0
- package/docs/functions/hooks_adsHooks.useAdsWriteValue.html +9 -0
- package/docs/functions/hooks_commandHooks.useRegisterSymbols.html +16 -0
- package/docs/functions/hooks_commandHooks.useTapValue.html +10 -0
- package/docs/functions/hooks_commandHooks.useWriteScaledValue.html +18 -0
- package/docs/functions/hooks_commandHooks.useWriteValue.html +11 -0
- package/docs/functions/hooks_useAutoCoreTag.ts.makeAutoCoreTagHooks.html +12 -0
- package/docs/functions/hooks_useScaledValue.useScaledValue.html +18 -0
- package/docs/functions/hub.createHub.html +3 -0
- package/docs/hierarchy.html +1 -0
- package/docs/index.html +148 -0
- package/docs/interfaces/components_IndicatorButton.IndicatorButtonProps.html +654 -0
- package/docs/interfaces/components_IndicatorRect.IndicatorRectProps.html +37 -0
- package/docs/interfaces/components_JogPanel.JogPanelButtonDefinition.html +5 -5
- package/docs/interfaces/components_ToggleGroup.ToggleGroupProps.html +545 -519
- package/docs/interfaces/core_AutoCoreTagTypes.BaseContextValue.html +12 -0
- package/docs/interfaces/core_AutoCoreTagTypes.ScaleConfig.html +13 -0
- package/docs/interfaces/core_EventEmitterContext.Action.html +8 -0
- package/docs/interfaces/core_EventEmitterContext.EventEmitterContextType.html +33 -0
- package/docs/interfaces/core_EventEmitterContext.State.html +8 -0
- package/docs/interfaces/core_EventEmitterContext.Subscription.html +6 -0
- package/docs/interfaces/core_IndicatorButtonState.IndicatorButtonState.html +10 -10
- package/docs/interfaces/core_PositionContext.IPositionContext.html +17 -0
- package/docs/interfaces/hub_CommandMessage.CommandMessage.html +6 -6
- package/docs/interfaces/hub_CommandMessage.CommandMessageResult.html +4 -4
- package/docs/modules/assets.html +1 -23
- package/docs/modules/assets_BlocklyLogo.html +1 -2
- package/docs/modules/assets_Distance.html +1 -2
- package/docs/modules/assets_JogLong.html +1 -2
- package/docs/modules/assets_JogMedium.html +1 -2
- package/docs/modules/assets_JogShort.html +1 -2
- package/docs/modules/assets_PythonLogo.html +1 -2
- package/docs/modules/assets_Rotation3D.html +1 -2
- package/docs/modules/assets_RotationCcw.html +1 -2
- package/docs/modules/assets_RotationCcwA.html +1 -2
- package/docs/modules/assets_RotationCcwB.html +1 -2
- package/docs/modules/assets_RotationCcwC.html +1 -2
- package/docs/modules/assets_RotationCw.html +1 -2
- package/docs/modules/assets_RotationCwA.html +1 -2
- package/docs/modules/assets_RotationCwB.html +1 -2
- package/docs/modules/assets_RotationCwC.html +1 -2
- package/docs/modules/assets_Run.html +1 -2
- package/docs/modules/assets_Speed.html +1 -2
- package/docs/modules/assets_SpeedFast.html +1 -2
- package/docs/modules/assets_SpeedMedium.html +1 -2
- package/docs/modules/assets_SpeedNone.html +1 -2
- package/docs/modules/assets_SpeedSlow.html +1 -2
- package/docs/modules/assets_Walk.html +1 -2
- package/docs/modules/components_AutoCoreDevPanel.html +20 -0
- package/docs/modules/components_BlocklyEditor.html +1 -5
- package/docs/modules/components_CodeEditor.html +1 -3
- package/docs/modules/components_FileList.html +1 -3
- package/docs/modules/components_FileSelect.html +1 -0
- package/docs/modules/components_FitText.html +1 -3
- package/docs/modules/components_Indicator.html +1 -0
- package/docs/modules/components_IndicatorButton.html +1 -0
- package/docs/modules/components_IndicatorRect.html +1 -0
- package/docs/modules/components_JogPanel.html +1 -9
- package/docs/modules/components_Lamp.html +1 -4
- package/docs/modules/components_Osk.html +1 -0
- package/docs/modules/components_OskDialog.html +1 -0
- package/docs/modules/components_ProgressBarWithValue.html +1 -0
- package/docs/modules/components_TextInput.html +1 -2
- package/docs/modules/components_ToggleGroup.html +1 -6
- package/docs/modules/components_ValueDisplay.html +1 -0
- package/docs/modules/components_ValueIndicator.html +1 -4
- package/docs/modules/components_ValueInput.html +1 -2
- package/docs/modules/core_ActionMode.html +1 -2
- package/docs/modules/core_AutoCoreTagContext.html +11 -0
- package/docs/modules/core_AutoCoreTagTypes.html +1 -0
- package/docs/modules/core_EventEmitterContext.html +53 -0
- package/docs/modules/core_IndicatorButtonState.html +1 -2
- package/docs/modules/core_IndicatorColor.html +1 -2
- package/docs/modules/core_MaskPatterns.html +1 -0
- package/docs/modules/core_NumerableTypes.html +1 -0
- package/docs/modules/core_PositionContext.html +1 -0
- package/docs/modules/core_UniqueId.html +1 -0
- package/docs/modules/core_ValueSimulator.html +1 -0
- package/docs/modules/core_hoc.html +1 -0
- package/docs/modules/hooks.html +1 -0
- package/docs/modules/hooks_adsHooks.html +1 -0
- package/docs/modules/hooks_commandHooks.html +1 -0
- package/docs/modules/hooks_useAutoCoreTag.ts.html +52 -0
- package/docs/modules/hooks_useScaledValue.html +1 -0
- package/docs/modules/hub.html +1 -0
- package/docs/modules/hub_CommandMessage.html +1 -3
- package/docs/modules/hub_HubBase.html +1 -0
- package/docs/modules/hub_HubSimulate.html +1 -0
- package/docs/modules/hub_HubTauri.html +1 -0
- package/docs/modules/hub_HubWebSocket.html +1 -2
- package/docs/modules.html +23 -0
- package/docs/types/components_IndicatorButton.IndicatorButtonOptionsType.html +1 -1
- package/docs/types/core_AutoCoreTagTypes.ExtractByTag.html +2 -0
- package/docs/types/core_AutoCoreTagTypes.PrimitiveKind.html +1 -0
- package/docs/types/core_AutoCoreTagTypes.TagConfig.html +16 -0
- package/docs/types/core_AutoCoreTagTypes.TagValueMap.html +1 -0
- package/docs/types/core_AutoCoreTagTypes.TagValueOf.html +1 -0
- package/docs/types/core_EventEmitterContext.EmitterDispatchFunction.html +3 -0
- package/docs/types/core_EventEmitterContext.EmitterSubscribeFunction.html +3 -0
- package/docs/types/core_EventEmitterContext.EmitterUnsubscribeFunction.html +3 -0
- package/docs/types/core_NumerableTypes.NumerableFormatOptions.html +4 -0
- package/docs/types/core_hoc.HocAddSubscriptionProps.html +6 -0
- package/docs/variables/components_AutoCoreDevPanel.AutoCoreDevPanel.html +43 -0
- package/docs/variables/components_BlocklyEditor.BlocklyEditor.html +13 -0
- package/docs/variables/components_BlocklyEditor.StandardToolbox.html +1 -1
- package/docs/variables/components_FileList.FileList.html +23 -0
- package/docs/variables/components_FileSelect.FileSelect.html +1 -0
- package/docs/variables/components_FitText.FitText.html +4 -0
- package/docs/variables/components_IndicatorButton.IndicatorButton.html +1 -0
- package/docs/variables/components_JogPanel.DefaultLinearJogButtons.html +2 -2
- package/docs/variables/components_JogPanel.DefaultRotationJogButtons.html +2 -2
- package/docs/variables/components_Osk.Osk.html +1 -0
- package/docs/variables/components_ProgressBarWithValue.ProgressBarWithValue.html +1 -0
- package/docs/variables/components_ToggleGroup.ToggleGroup.html +1 -0
- package/docs/variables/components_ValueInput.ValueInput.html +4 -0
- package/docs/variables/core_AutoCoreTagContext.AutoCoreTagContext.html +1 -0
- package/docs/variables/core_AutoCoreTagContext.AutoCoreTagProvider.html +7 -0
- package/docs/variables/core_EventEmitterContext.EventEmitterContext.html +64 -0
- package/docs/variables/core_EventEmitterContext.EventEmitterProvider.html +10 -0
- package/docs/variables/core_MaskPatterns.PrimeReactMaskPatterns.html +14 -0
- package/docs/variables/core_MaskPatterns.RegExMaskPatterns.html +15 -0
- package/docs/variables/core_PositionContext.DimensionsContext.html +6 -0
- package/docs/variables/hooks_useScaledValue.kMillimeters2Inches.html +2 -0
- package/docs/variables/hooks_useScaledValue.kNewtons2Pounds.html +2 -0
- package/package.json +32 -27
- package/readme.md +193 -22
- package/src/components/AutoCoreDevPanel.tsx +411 -0
- package/src/components/CodeEditor.tsx +2 -2
- package/src/components/FileList.tsx +2 -2
- package/src/components/Indicator.tsx +2 -2
- package/src/components/IndicatorButton.tsx +187 -333
- package/src/components/IndicatorRect.tsx +2 -2
- package/src/components/Lamp.tsx +3 -3
- package/src/components/TextInput.tsx +159 -240
- package/src/components/ToggleGroup.tsx +3 -3
- package/src/components/ValueDisplay.tsx +4 -4
- package/src/components/ValueIndicator.tsx +2 -2
- package/src/components/ValueInput.tsx +2 -2
- package/src/core/AutoCoreTagContext.tsx +698 -0
- package/src/core/AutoCoreTagTypes.ts +202 -0
- package/src/core/EventEmitterContext.tsx +582 -225
- package/src/core/ValueSimulator.ts +2 -2
- package/src/hooks/useAutoCoreTag.ts +103 -0
- package/src/hub/HubBase.ts +3 -3
- package/src/hub/HubSimulate.ts +2 -2
- package/src/hub/HubTauri.ts +3 -3
- package/src/hub/HubWebSocket.ts +29 -32
- package/src/hub/index.ts +2 -2
- package/tsconfig.json +43 -28
- package/docs/classes/components_BlocklyEditor.BlocklyEditor.html +0 -124
- package/docs/classes/components_ValueInput.ValueInput.html +0 -113
- package/docs/functions/assets_BlocklyLogo.default.html +0 -1
- package/docs/functions/assets_Distance.default.html +0 -1
- package/docs/functions/assets_JogLong.default.html +0 -1
- package/docs/functions/assets_JogMedium.default.html +0 -1
- package/docs/functions/assets_JogShort.default.html +0 -1
- package/docs/functions/assets_PythonLogo.default.html +0 -1
- package/docs/functions/assets_Rotation3D.default.html +0 -1
- package/docs/functions/assets_RotationCcw.default.html +0 -1
- package/docs/functions/assets_RotationCcwA.default.html +0 -1
- package/docs/functions/assets_RotationCcwB.default.html +0 -1
- package/docs/functions/assets_RotationCcwC.default.html +0 -1
- package/docs/functions/assets_RotationCw.default.html +0 -1
- package/docs/functions/assets_RotationCwA.default.html +0 -1
- package/docs/functions/assets_RotationCwB.default.html +0 -1
- package/docs/functions/assets_RotationCwC.default.html +0 -1
- package/docs/functions/assets_Run.default.html +0 -1
- package/docs/functions/assets_Speed.default.html +0 -1
- package/docs/functions/assets_SpeedFast.default.html +0 -1
- package/docs/functions/assets_SpeedMedium.default.html +0 -1
- package/docs/functions/assets_SpeedNone.default.html +0 -1
- package/docs/functions/assets_SpeedSlow.default.html +0 -1
- package/docs/functions/assets_Walk.default.html +0 -1
- package/docs/functions/components_FileList.FileList.html +0 -21
- package/docs/functions/components_FitText.FitText.html +0 -8
- package/docs/functions/components_ToggleGroup.ToggleGroup.html +0 -5
|
@@ -0,0 +1,698 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (C) 2025 Automated Design Corp.. All Rights Reserved.
|
|
3
|
+
* Created Date: 2025-09-05 07:35:46
|
|
4
|
+
* -----
|
|
5
|
+
* Last Modified: 2025-09-10 11:28:01
|
|
6
|
+
* -----
|
|
7
|
+
*
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @module core/AutoCoreTagContext
|
|
12
|
+
*
|
|
13
|
+
* @document ../../additional-docs/AutCoreTagContext.md
|
|
14
|
+
*
|
|
15
|
+
* @summary
|
|
16
|
+
* A React Context + Provider that:
|
|
17
|
+
* - Buffers **raw** controller values for every tag (exactly as received)
|
|
18
|
+
* - Derives **display** values from raw using current `scales` and optional tag `codec`
|
|
19
|
+
* - Recomputes display values **from raw** whenever a scale changes (no lossy re-scaling)
|
|
20
|
+
* - Inverse-scales on `write()` so the server always receives controller units
|
|
21
|
+
* - Supports ADS one-shot refresh, GNV-style scale objects, and resilient eager reads
|
|
22
|
+
*
|
|
23
|
+
* @remarks
|
|
24
|
+
* ❖ **Two representations per tag**
|
|
25
|
+
* - `rawValues[tagName]`: last controller value as-is (pre-scale, pre-codec)
|
|
26
|
+
* - `values[tagName]`: app-visible value derived from raw (scales/codec applied)
|
|
27
|
+
*
|
|
28
|
+
* ❖ **Scaling**
|
|
29
|
+
* - Provide `scales` keyed by scale group (e.g., `"position"`, `"load"`).
|
|
30
|
+
* - Each scale may point at a server tag (`serverTag`) that publishes an object
|
|
31
|
+
* `{ name, scale, label }` (GNV-style). When received, the Provider recomputes
|
|
32
|
+
* *only* affected display values **from raw**.
|
|
33
|
+
* - Manual `updateScale(name, scale, label)` writes the object back to the server
|
|
34
|
+
* (if `serverTag` is configured) and recomputes from raw locally.
|
|
35
|
+
*
|
|
36
|
+
* ❖ **Lifecycle order (eagerRead = true)**
|
|
37
|
+
* 1. Pull server scales first (so first ADS burst displays in correct units)
|
|
38
|
+
* 2. Register ADS symbols and subscribe all domains
|
|
39
|
+
* 3. Eager-pull non-ADS (refresh if available, else read_value)
|
|
40
|
+
* 4. ADS `refresh` one-shot publish
|
|
41
|
+
*
|
|
42
|
+
* ❖ **Writes**
|
|
43
|
+
* - `write(tagName, displayValue)` → (codec?) → inverse-scale → `write_value`
|
|
44
|
+
* - `tap(tagName)` pulses booleans `true → (300ms) → false` with proper domain envelopes
|
|
45
|
+
*
|
|
46
|
+
* ❖ **Resilience**
|
|
47
|
+
* - Eager reads tolerate “missing key” errors on fresh systems and keep going
|
|
48
|
+
* - All re-scaling recomputes from **raw** to avoid cumulative precision/race issues
|
|
49
|
+
*
|
|
50
|
+
* @example Minimal wiring
|
|
51
|
+
* ```tsx
|
|
52
|
+
* import { AutoCoreTagProvider } from "@adcops/autocore-react/core/AutoCoreTagContext";
|
|
53
|
+
* import type { TagConfig, ScaleConfig } from "@adcops/autocore-react/core/AutoCoreTagTypes";
|
|
54
|
+
*
|
|
55
|
+
* const acTagSpec = [
|
|
56
|
+
* { tagName: "pressPosition", domain: "ADS", valueType: "number", symbolName: "AX.Press.Position", scale: "position" },
|
|
57
|
+
* { tagName: "pressLoad", domain: "ADS", valueType: "number", symbolName: "AX.Press.Load", scale: "load" },
|
|
58
|
+
* { tagName: "isMotorsOn", domain: "ADS", valueType: "boolean", symbolName: "GIO.isMotorsOn" },
|
|
59
|
+
* ] as const satisfies readonly TagConfig[];
|
|
60
|
+
*
|
|
61
|
+
* const scales: Record<string, ScaleConfig> = {
|
|
62
|
+
* position: {
|
|
63
|
+
* name: "position",
|
|
64
|
+
* scale: 1.0,
|
|
65
|
+
* label: "mm",
|
|
66
|
+
* serverTag: { domain: "GNV", symbolName: "position_units" }, // expects {name, scale, label}
|
|
67
|
+
* },
|
|
68
|
+
* load: {
|
|
69
|
+
* name: "load",
|
|
70
|
+
* scale: 1.0,
|
|
71
|
+
* label: "N",
|
|
72
|
+
* serverTag: { domain: "GNV", symbolName: "load_units" }, // expects {name, scale, label}
|
|
73
|
+
* },
|
|
74
|
+
* };
|
|
75
|
+
*
|
|
76
|
+
* export function AppRoot() {
|
|
77
|
+
* return (
|
|
78
|
+
* <AutoCoreTagProvider tags={acTagSpec} scales={scales} eagerRead>
|
|
79
|
+
* <App />
|
|
80
|
+
* </AutoCoreTagProvider>
|
|
81
|
+
* );
|
|
82
|
+
* }
|
|
83
|
+
* ```
|
|
84
|
+
*
|
|
85
|
+
* @example Consuming values with hooks
|
|
86
|
+
* ```tsx
|
|
87
|
+
* import { makeAutoCoreTagHooks } from "@adcops/autocore-react/hooks/useAutoCoreTag";
|
|
88
|
+
* import { AutoCoreTagContext } from "@adcops/autocore-react/core/AutoCoreTagContext";
|
|
89
|
+
*
|
|
90
|
+
* export const AutoCoreHooks = makeAutoCoreTagHooks(AutoCoreTagContext, acTagSpec);
|
|
91
|
+
*
|
|
92
|
+
* function Dashboard() {
|
|
93
|
+
* const { value: pos } = AutoCoreHooks.useAutoCoreTag("pressPosition"); // display units
|
|
94
|
+
* const { value: load } = AutoCoreHooks.useAutoCoreTag("pressLoad");
|
|
95
|
+
* const { scales, updateScale } = AutoCoreHooks.useScales();
|
|
96
|
+
*
|
|
97
|
+
* return (
|
|
98
|
+
* <>
|
|
99
|
+
* <div>Position: {pos} {scales.position.label}</div>
|
|
100
|
+
* <div>Load: {load} {scales.load.label}</div>
|
|
101
|
+
* <button onClick={() => updateScale("position", 1/25.4, "in")}>inches</button>
|
|
102
|
+
* </>
|
|
103
|
+
* );
|
|
104
|
+
* }
|
|
105
|
+
* ```
|
|
106
|
+
*/
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
import React, {
|
|
110
|
+
useRef,
|
|
111
|
+
createContext,
|
|
112
|
+
useCallback,
|
|
113
|
+
useContext,
|
|
114
|
+
useEffect,
|
|
115
|
+
useMemo,
|
|
116
|
+
useState,
|
|
117
|
+
type ReactNode,
|
|
118
|
+
} from "react";
|
|
119
|
+
import { EventEmitterContext } from "./EventEmitterContext";
|
|
120
|
+
import type {
|
|
121
|
+
BaseContextValue,
|
|
122
|
+
TagConfig,
|
|
123
|
+
ScaleConfig,
|
|
124
|
+
} from "./AutoCoreTagTypes";
|
|
125
|
+
|
|
126
|
+
type VMapRuntime = Record<string, unknown>;
|
|
127
|
+
|
|
128
|
+
export const AutoCoreTagContext = createContext<BaseContextValue<VMapRuntime>>({
|
|
129
|
+
values: {},
|
|
130
|
+
rawValues: {},
|
|
131
|
+
isLoading: true,
|
|
132
|
+
write: async () => { },
|
|
133
|
+
tap: async () => { },
|
|
134
|
+
scales: {},
|
|
135
|
+
updateScale: async () => { },
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
type HubEnvelope<T> = { success?: boolean; valid?: boolean; data?: T };
|
|
139
|
+
|
|
140
|
+
/** Small sleep helper */
|
|
141
|
+
const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* AutoCoreTagProvider
|
|
146
|
+
*
|
|
147
|
+
* @description
|
|
148
|
+
* React Provider that wires up AutoCore tags to live server updates, buffers **raw**
|
|
149
|
+
* controller values, exposes **display** values (scales/codec applied), and handles
|
|
150
|
+
* writes/taps with proper domain envelopes. Scaling is **always** applied to display
|
|
151
|
+
* values only; raw values remain untouched and are the single source of truth.
|
|
152
|
+
*
|
|
153
|
+
* @props
|
|
154
|
+
* - `tags: readonly TagConfig[]`
|
|
155
|
+
* The full tag spec. Each tag declares `tagName`, `domain`, `symbolName`,
|
|
156
|
+
* `valueType` ("boolean"|"number"|"string"|"json"), optional `scale` name, and
|
|
157
|
+
* optional `codec` for JSON.
|
|
158
|
+
*
|
|
159
|
+
* - `scales?: Record<string, ScaleConfig>`
|
|
160
|
+
* Map of scale groups (`position`, `load`, …). Each scale may include an optional
|
|
161
|
+
* `serverTag` `{ domain, symbolName }`. When present, the provider reads that key
|
|
162
|
+
* first and subscribes to updates. The server must publish a GNV-style object
|
|
163
|
+
* `{ name, scale, label }` (stringified or object). When a new scale arrives,
|
|
164
|
+
* the provider recomputes affected display values **from raw**.
|
|
165
|
+
*
|
|
166
|
+
* - `eagerRead?: boolean = true`
|
|
167
|
+
* If true, the provider performs a non-ADS eager fetch pass (refresh if available,
|
|
168
|
+
* otherwise read_value with backoff) and then performs a single ADS `refresh`.
|
|
169
|
+
* Missing keys are common on clean systems—these are logged and skipped.
|
|
170
|
+
*
|
|
171
|
+
* - `children: ReactNode`
|
|
172
|
+
* Your app subtree that consumes `AutoCoreTagContext`.
|
|
173
|
+
*
|
|
174
|
+
* @context value
|
|
175
|
+
* - `values`: Partial<Record<tagName, unknown>> — app-visible (scaled/decoded)
|
|
176
|
+
* - `rawValues`: Record<tagName, unknown> — last controller values as received
|
|
177
|
+
* - `isLoading`: boolean — true until initial wiring completes
|
|
178
|
+
* - `write(tagName, displayValue)`: Promise<void>
|
|
179
|
+
* Serializes/encodes JSON if needed and inverse-scales numbers back to raw units.
|
|
180
|
+
* Dispatches `write_value` with appropriate domain envelope:
|
|
181
|
+
* - ADS: `{ symbol_name, value }`
|
|
182
|
+
* - GNV: `{ group:"ux", key, value }`
|
|
183
|
+
* - Other: `{ key, value }`
|
|
184
|
+
* - `tap(tagName)`: Promise<void>
|
|
185
|
+
* For boolean tags only. Pulses true → 300ms → false with the proper envelope.
|
|
186
|
+
* - `scales`: Record<string, ScaleConfig> — current factors/labels
|
|
187
|
+
* - `updateScale(name, scale, label)`: Promise<void>
|
|
188
|
+
* Writes `{ name, scale, label }` to the configured `serverTag` (if present) and
|
|
189
|
+
* recomputes display values **from raw** locally.
|
|
190
|
+
*
|
|
191
|
+
* @example With server-driven scales (GNV) and ADS data
|
|
192
|
+
* ```tsx
|
|
193
|
+
* const tags: readonly TagConfig[] = [
|
|
194
|
+
* { tagName: "pressPosition", domain: "ADS", valueType: "number", symbolName: "AX.Press.Pos", scale: "position" },
|
|
195
|
+
* { tagName: "pressLoad", domain: "ADS", valueType: "number", symbolName: "AX.Press.Load", scale: "load" },
|
|
196
|
+
* { tagName: "isMotorsOn", domain: "ADS", valueType: "boolean", symbolName: "GIO.isMotorsOn" },
|
|
197
|
+
* // JSON with codec example
|
|
198
|
+
* { tagName: "jobMeta", domain: "GNV", valueType: "json", symbolName: "job_meta",
|
|
199
|
+
* codec: {
|
|
200
|
+
* fromServer: (raw) => (typeof raw === "string" ? JSON.parse(raw) : raw),
|
|
201
|
+
* toServer: (val) => JSON.stringify(val),
|
|
202
|
+
* }
|
|
203
|
+
* },
|
|
204
|
+
* ] as const;
|
|
205
|
+
*
|
|
206
|
+
* const scales: Record<string, ScaleConfig> = {
|
|
207
|
+
* position: {
|
|
208
|
+
* name: "position",
|
|
209
|
+
* scale: 1, label: "mm",
|
|
210
|
+
* serverTag: { domain: "GNV", symbolName: "position_units" } // expects {name, scale, label}
|
|
211
|
+
* },
|
|
212
|
+
* load: {
|
|
213
|
+
* name: "load",
|
|
214
|
+
* scale: 1, label: "N",
|
|
215
|
+
* serverTag: { domain: "GNV", symbolName: "load_units" } // expects {name, scale, label}
|
|
216
|
+
* }
|
|
217
|
+
* };
|
|
218
|
+
*
|
|
219
|
+
* <AutoCoreTagProvider tags={tags} scales={scales} eagerRead>
|
|
220
|
+
* <YourApp/>
|
|
221
|
+
* </AutoCoreTagProvider>
|
|
222
|
+
* ```
|
|
223
|
+
*
|
|
224
|
+
* @example Reading values, raw vs display, and writing
|
|
225
|
+
* ```tsx
|
|
226
|
+
* import { makeAutoCoreTagHooks } from "../hooks/useAutoCoreTag";
|
|
227
|
+
* import { AutoCoreTagContext } from "../core/AutoCoreTagContext";
|
|
228
|
+
*
|
|
229
|
+
* const Hooks = makeAutoCoreTagHooks(AutoCoreTagContext, tags);
|
|
230
|
+
*
|
|
231
|
+
* function Status() {
|
|
232
|
+
* const { value: pos, isLoading } = Hooks.useAutoCoreTag("pressPosition"); // scaled
|
|
233
|
+
* const { value: rawPos } = (() => {
|
|
234
|
+
* // access raw via context when needed for debugging
|
|
235
|
+
* const ctx = React.useContext(AutoCoreTagContext);
|
|
236
|
+
* return { value: ctx.rawValues["pressPosition"] };
|
|
237
|
+
* })();
|
|
238
|
+
*
|
|
239
|
+
* const { scales, updateScale } = Hooks.useScales();
|
|
240
|
+
*
|
|
241
|
+
* return (
|
|
242
|
+
* <>
|
|
243
|
+
* <div>Pos: {pos} {scales.position.label} (raw: {String(rawPos)})</div>
|
|
244
|
+
* <button onClick={() => updateScale("position", 1/25.4, "in")}>inches</button>
|
|
245
|
+
* </>
|
|
246
|
+
* );
|
|
247
|
+
* }
|
|
248
|
+
* ```
|
|
249
|
+
*
|
|
250
|
+
* @example Tapping booleans and writing numbers in display units
|
|
251
|
+
* ```tsx
|
|
252
|
+
* const { tap } = Hooks.useAutoCoreTag("isMotorsOn");
|
|
253
|
+
* const { write } = Hooks.useAutoCoreTag("pressPosition");
|
|
254
|
+
*
|
|
255
|
+
* <button onClick={() => tap()}>Motors TAP</button>
|
|
256
|
+
* <button onClick={() => write(10.0)}>Jog to 10 (display units)</button>
|
|
257
|
+
* ```
|
|
258
|
+
*/
|
|
259
|
+
export const AutoCoreTagProvider: React.FC<{
|
|
260
|
+
children: ReactNode;
|
|
261
|
+
tags: readonly TagConfig[];
|
|
262
|
+
scales?: Record<string, ScaleConfig>;
|
|
263
|
+
eagerRead?: boolean;
|
|
264
|
+
}> = ({ children, tags, scales = {}, eagerRead = true }) => {
|
|
265
|
+
const startedRef = useRef(false);
|
|
266
|
+
|
|
267
|
+
const { invoke, isConnected, subscribe, unsubscribe } =
|
|
268
|
+
useContext(EventEmitterContext);
|
|
269
|
+
|
|
270
|
+
/** Raw (controller) values as received from the server (pre-scale, pre-codec). */
|
|
271
|
+
const [rawValues, setRawValues] = useState<Record<string, unknown>>(() => {
|
|
272
|
+
const seed: Record<string, unknown> = {};
|
|
273
|
+
for (const t of tags) {
|
|
274
|
+
if (t.initialValue !== undefined) {
|
|
275
|
+
// Interpret initialValue as **raw**.
|
|
276
|
+
seed[t.tagName] = t.initialValue;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
return seed;
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
/** App-visible display values, computed from raw using scales/codecs. */
|
|
283
|
+
const [values, setValues] = useState<Record<string, unknown>>({});
|
|
284
|
+
|
|
285
|
+
/** Scales (current factor/label) */
|
|
286
|
+
const [scaleValues, setScaleValues] =
|
|
287
|
+
useState<Record<string, ScaleConfig>>(scales);
|
|
288
|
+
|
|
289
|
+
/** Keep refs for subscription callbacks without re-subscribing */
|
|
290
|
+
const scaleRef = useRef(scaleValues);
|
|
291
|
+
const rawRef = useRef(rawValues);
|
|
292
|
+
useEffect(() => { scaleRef.current = scaleValues; }, [scaleValues]);
|
|
293
|
+
useEffect(() => { rawRef.current = rawValues; }, [rawValues]);
|
|
294
|
+
|
|
295
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
296
|
+
|
|
297
|
+
/** Produce a display value from a raw value given the tag config + current scales. */
|
|
298
|
+
const toDisplay = useCallback((tag: TagConfig, raw: unknown): unknown => {
|
|
299
|
+
const { valueType, scale, codec } = tag;
|
|
300
|
+
|
|
301
|
+
// 1) numeric scaling
|
|
302
|
+
if (valueType === "number" && typeof raw === "number" && scale) {
|
|
303
|
+
const s = scaleRef.current[scale];
|
|
304
|
+
const factor = s?.scale ?? 1;
|
|
305
|
+
return raw * factor;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// 2) codec for json (optional)
|
|
309
|
+
if (valueType === "json" && codec?.fromServer) {
|
|
310
|
+
try { return codec.fromServer(raw); } catch { /* fall through */ }
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// 3) pass-through
|
|
314
|
+
return raw;
|
|
315
|
+
}, []);
|
|
316
|
+
|
|
317
|
+
/** Inverse of toDisplay for writes (display -> raw server value) */
|
|
318
|
+
const toServer = useCallback((tag: TagConfig, display: unknown): unknown => {
|
|
319
|
+
const { valueType, scale, codec } = tag;
|
|
320
|
+
|
|
321
|
+
// invert codec first (json)
|
|
322
|
+
if (valueType === "json" && codec?.toServer) {
|
|
323
|
+
try { display = codec.toServer(display as any); } catch { /* fall through */ }
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// inverse numeric scaling
|
|
327
|
+
if (valueType === "number" && typeof display === "number" && scale) {
|
|
328
|
+
const s = scaleRef.current[scale];
|
|
329
|
+
const factor = s?.scale ?? 1;
|
|
330
|
+
return display / factor;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
return display;
|
|
334
|
+
}, []);
|
|
335
|
+
|
|
336
|
+
/** Recompute display values for all tags in this scale from **raw** */
|
|
337
|
+
const rescaleFromRaw = useCallback((scaleName: string) => {
|
|
338
|
+
const affected = tags.filter(t => t.scale === scaleName);
|
|
339
|
+
if (!affected.length) return;
|
|
340
|
+
|
|
341
|
+
setValues(prev => {
|
|
342
|
+
const next = { ...prev };
|
|
343
|
+
for (const tag of affected) {
|
|
344
|
+
const raw = rawRef.current[tag.tagName];
|
|
345
|
+
if (typeof raw !== "number") continue;
|
|
346
|
+
const disp = toDisplay(tag, raw);
|
|
347
|
+
if (next[tag.tagName] !== disp) next[tag.tagName] = disp;
|
|
348
|
+
}
|
|
349
|
+
return next;
|
|
350
|
+
});
|
|
351
|
+
}, [tags, toDisplay]);
|
|
352
|
+
|
|
353
|
+
/** Subscribe handler for tag updates: buffer raw, compute display. */
|
|
354
|
+
const handleTagUpdate = useCallback((tag: TagConfig, raw: unknown) => {
|
|
355
|
+
// write raw (immutably)
|
|
356
|
+
setRawValues(prev =>
|
|
357
|
+
prev[tag.tagName] === raw ? prev : { ...prev, [tag.tagName]: raw }
|
|
358
|
+
);
|
|
359
|
+
// compute display from raw
|
|
360
|
+
const display = toDisplay(tag, raw);
|
|
361
|
+
setValues(prev =>
|
|
362
|
+
prev[tag.tagName] === display ? prev : { ...prev, [tag.tagName]: display }
|
|
363
|
+
);
|
|
364
|
+
}, [toDisplay]);
|
|
365
|
+
|
|
366
|
+
/** Eager pulls (non-ADS): read raw and run handleTagUpdate */
|
|
367
|
+
const eagerPullNonADS = useCallback(
|
|
368
|
+
async (
|
|
369
|
+
domain: string,
|
|
370
|
+
tagList: readonly TagConfig[],
|
|
371
|
+
opts?: { concurrency?: number; minDelayMs?: number; jitterMs?: number }
|
|
372
|
+
) => {
|
|
373
|
+
const concurrency = opts?.concurrency ?? 4;
|
|
374
|
+
const minDelayMs = opts?.minDelayMs ?? 20;
|
|
375
|
+
const jitterMs = opts?.jitterMs ?? 40;
|
|
376
|
+
|
|
377
|
+
let index = 0;
|
|
378
|
+
const workers = Array.from({ length: concurrency }, () => (async () => {
|
|
379
|
+
while (true) {
|
|
380
|
+
const i = index++;
|
|
381
|
+
if (i >= tagList.length) return;
|
|
382
|
+
const tag = tagList[i];
|
|
383
|
+
|
|
384
|
+
try {
|
|
385
|
+
let usedPublishPath = false;
|
|
386
|
+
try {
|
|
387
|
+
await invoke(domain, "refresh", { topic: tag.symbolName });
|
|
388
|
+
usedPublishPath = true;
|
|
389
|
+
} catch { /* fall through */ }
|
|
390
|
+
|
|
391
|
+
if (!usedPublishPath) {
|
|
392
|
+
const payload =
|
|
393
|
+
domain.toUpperCase() === "GNV"
|
|
394
|
+
? { group: "ux", key: tag.symbolName }
|
|
395
|
+
: { key: tag.symbolName };
|
|
396
|
+
|
|
397
|
+
if (tag.options) (payload as any).options = tag.options;
|
|
398
|
+
|
|
399
|
+
try {
|
|
400
|
+
const resp: any = await invoke(domain, "read_value", payload);
|
|
401
|
+
// Server always returns { success, valid, data }
|
|
402
|
+
if (resp?.success && resp?.valid) {
|
|
403
|
+
handleTagUpdate(tag, resp.data);
|
|
404
|
+
}
|
|
405
|
+
} catch (err) {
|
|
406
|
+
// Missing key on fresh systems is normal; keep going.
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
} catch (outerErr) {
|
|
410
|
+
// never throw out of the worker loop
|
|
411
|
+
// console.warn(`eager pull worker error for ${domain}/${tag.symbolName}`, outerErr);
|
|
412
|
+
} finally {
|
|
413
|
+
const extra = Math.floor(Math.random() * jitterMs);
|
|
414
|
+
await sleep(minDelayMs + extra);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
})());
|
|
418
|
+
|
|
419
|
+
await Promise.all(workers);
|
|
420
|
+
},
|
|
421
|
+
[invoke, handleTagUpdate]
|
|
422
|
+
);
|
|
423
|
+
|
|
424
|
+
/** Pull server scale objects first thing (GNV envelope) */
|
|
425
|
+
const pullServerScales = useCallback(async () => {
|
|
426
|
+
for (const [scaleName, cfg] of Object.entries(scales)) {
|
|
427
|
+
if (!cfg.serverTag) continue;
|
|
428
|
+
const { domain, symbolName } = cfg.serverTag;
|
|
429
|
+
|
|
430
|
+
try {
|
|
431
|
+
const respUnknown = await invoke(domain, "read_value", {
|
|
432
|
+
group: "ux",
|
|
433
|
+
key: symbolName,
|
|
434
|
+
});
|
|
435
|
+
|
|
436
|
+
// narrow at runtime instead of forcing a direct cast
|
|
437
|
+
const env = respUnknown as HubEnvelope<string>;
|
|
438
|
+
if (env.data && (env.success ?? true) && (env.valid ?? true)) {
|
|
439
|
+
|
|
440
|
+
const env_data = JSON.parse(env.data) as ScaleConfig;
|
|
441
|
+
if (env_data && typeof env_data.scale === "number" ) {
|
|
442
|
+
const { scale, label } = env_data;
|
|
443
|
+
setScaleValues(prev => ({
|
|
444
|
+
...prev,
|
|
445
|
+
[scaleName]: {
|
|
446
|
+
...prev[scaleName],
|
|
447
|
+
scale,
|
|
448
|
+
label: label ?? prev[scaleName]?.label ?? "---",
|
|
449
|
+
},
|
|
450
|
+
}));
|
|
451
|
+
rescaleFromRaw(scaleName);
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
} catch {
|
|
455
|
+
// Ok if not present yet.
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
}, [invoke, scales, rescaleFromRaw]);
|
|
459
|
+
|
|
460
|
+
// Main subscription wiring
|
|
461
|
+
useEffect(() => {
|
|
462
|
+
let mounted = true;
|
|
463
|
+
const subscriptions: number[] = [];
|
|
464
|
+
|
|
465
|
+
const registerAndSubscribe = async () => {
|
|
466
|
+
// group tags by domain
|
|
467
|
+
const tagsByDomain = new Map<string, TagConfig[]>();
|
|
468
|
+
for (const tag of tags) {
|
|
469
|
+
const list = tagsByDomain.get(tag.domain);
|
|
470
|
+
if (list) list.push(tag); else tagsByDomain.set(tag.domain, [tag]);
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
try {
|
|
474
|
+
// 0) load scales first so first ADS values get correct factor
|
|
475
|
+
await pullServerScales();
|
|
476
|
+
|
|
477
|
+
// 1) ADS register (sequential is fine)
|
|
478
|
+
for (const [domain, tagList] of tagsByDomain.entries()) {
|
|
479
|
+
if (domain.toUpperCase() === "ADS") {
|
|
480
|
+
for (const tag of tagList) {
|
|
481
|
+
try {
|
|
482
|
+
const invokeOptions = tag.options
|
|
483
|
+
? { symbol_name: tag.symbolName, options: tag.options }
|
|
484
|
+
: { symbol_name: tag.symbolName };
|
|
485
|
+
await invoke("ADS", "register_symbol", invokeOptions);
|
|
486
|
+
} catch (ex) {
|
|
487
|
+
console.error(`Failed to register symbol ${tag.symbolName}: ${ex}`);
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
// 2) subscribe
|
|
493
|
+
for (const tag of tagList) {
|
|
494
|
+
const id = subscribe(`${domain}/${tag.symbolName}`, (data) => {
|
|
495
|
+
if (!mounted) return;
|
|
496
|
+
handleTagUpdate(tag, data?.value);
|
|
497
|
+
});
|
|
498
|
+
subscriptions.push(id);
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
// 3) eager reads (non-ADS)
|
|
502
|
+
if (eagerRead && domain.toUpperCase() !== "ADS") {
|
|
503
|
+
await eagerPullNonADS(domain, tagList, { concurrency: 4, minDelayMs: 20, jitterMs: 40 });
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
// 4) ADS one-shot refresh (after scales are known)
|
|
508
|
+
if (eagerRead) {
|
|
509
|
+
await invoke("ADS", "refresh", {});
|
|
510
|
+
}
|
|
511
|
+
} finally {
|
|
512
|
+
if (mounted) setTimeout(() => mounted && setIsLoading(false), 100);
|
|
513
|
+
}
|
|
514
|
+
};
|
|
515
|
+
|
|
516
|
+
const safeRegister = async () => {
|
|
517
|
+
if (!mounted || startedRef.current) return;
|
|
518
|
+
startedRef.current = true;
|
|
519
|
+
try { await registerAndSubscribe(); }
|
|
520
|
+
finally { if (mounted) setTimeout(() => mounted && setIsLoading(false), 100); }
|
|
521
|
+
};
|
|
522
|
+
|
|
523
|
+
if (!isConnected()) {
|
|
524
|
+
const id = subscribe("HUB/connected", () => {
|
|
525
|
+
unsubscribe(id);
|
|
526
|
+
void safeRegister();
|
|
527
|
+
});
|
|
528
|
+
subscriptions.push(id);
|
|
529
|
+
} else {
|
|
530
|
+
void safeRegister();
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
return () => {
|
|
534
|
+
mounted = false;
|
|
535
|
+
subscriptions.forEach(unsubscribe);
|
|
536
|
+
startedRef.current = false;
|
|
537
|
+
};
|
|
538
|
+
}, [subscribe, unsubscribe, isConnected, invoke, eagerRead, tags, pullServerScales, eagerPullNonADS, handleTagUpdate]);
|
|
539
|
+
|
|
540
|
+
/** Subscribe to server-driven scale tags (GNV object), recompute displays from raw. */
|
|
541
|
+
const scaleServerSubs = useMemo(
|
|
542
|
+
() =>
|
|
543
|
+
Object.entries(scales)
|
|
544
|
+
.filter(([, cfg]) => cfg.serverTag)
|
|
545
|
+
.map(([scaleName, cfg]) => ({
|
|
546
|
+
scaleName,
|
|
547
|
+
domain: cfg.serverTag!.domain,
|
|
548
|
+
symbolName: cfg.serverTag!.symbolName,
|
|
549
|
+
})),
|
|
550
|
+
[scales]
|
|
551
|
+
);
|
|
552
|
+
|
|
553
|
+
useEffect(() => {
|
|
554
|
+
let mounted = true;
|
|
555
|
+
const subs: number[] = [];
|
|
556
|
+
|
|
557
|
+
for (const { scaleName, domain, symbolName } of scaleServerSubs) {
|
|
558
|
+
const id = subscribe(`${domain}/${symbolName}`, (data) => {
|
|
559
|
+
if (!mounted) return;
|
|
560
|
+
const v = data?.value;
|
|
561
|
+
if (v && typeof v === "object" && typeof (v as any).scale === "number") {
|
|
562
|
+
const { scale, label } = v as { scale: number; label?: string };
|
|
563
|
+
setScaleValues(prev => ({
|
|
564
|
+
...prev,
|
|
565
|
+
[scaleName]: {
|
|
566
|
+
...prev[scaleName],
|
|
567
|
+
scale,
|
|
568
|
+
label: label ?? prev[scaleName]?.label ?? "---",
|
|
569
|
+
},
|
|
570
|
+
}));
|
|
571
|
+
rescaleFromRaw(scaleName);
|
|
572
|
+
}
|
|
573
|
+
});
|
|
574
|
+
subs.push(id);
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
return () => {
|
|
578
|
+
mounted = false;
|
|
579
|
+
subs.forEach(unsubscribe);
|
|
580
|
+
};
|
|
581
|
+
}, [subscribe, unsubscribe, scaleServerSubs, rescaleFromRaw]);
|
|
582
|
+
|
|
583
|
+
/** Write with inverse scaling and proper domain envelopes. */
|
|
584
|
+
const write = useCallback(
|
|
585
|
+
async (tagName: string, displayValue: unknown) => {
|
|
586
|
+
const cfg = tags.find((t) => t.tagName === tagName);
|
|
587
|
+
if (!cfg) {
|
|
588
|
+
console.error(`write(): unknown tag '${tagName}'`);
|
|
589
|
+
return;
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
const serverValue = toServer(cfg, displayValue);
|
|
593
|
+
|
|
594
|
+
let payload: any;
|
|
595
|
+
const dom = cfg.domain.toUpperCase();
|
|
596
|
+
if (dom === "ADS") {
|
|
597
|
+
payload = { symbol_name: cfg.symbolName, value: serverValue };
|
|
598
|
+
} else if (dom === "GNV") {
|
|
599
|
+
payload = { group: "ux", key: cfg.symbolName, value: serverValue };
|
|
600
|
+
} else {
|
|
601
|
+
payload = { key: cfg.symbolName, value: serverValue };
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
await invoke(cfg.domain, "write_value", payload);
|
|
605
|
+
},
|
|
606
|
+
[tags, invoke, toServer]
|
|
607
|
+
);
|
|
608
|
+
|
|
609
|
+
/** Tap (boolean pulse) */
|
|
610
|
+
const tap = useCallback(
|
|
611
|
+
async (tagName: string) => {
|
|
612
|
+
const cfg = tags.find((t) => t.tagName === tagName);
|
|
613
|
+
if (!cfg) {
|
|
614
|
+
console.error(`tap(): unknown tag '${tagName}'`);
|
|
615
|
+
return;
|
|
616
|
+
}
|
|
617
|
+
if (cfg.valueType !== "boolean") {
|
|
618
|
+
console.warn(`tap(): tag '${tagName}' is not a boolean type`);
|
|
619
|
+
return;
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
const dom = cfg.domain.toUpperCase();
|
|
623
|
+
const mkPayload = (val: boolean) =>
|
|
624
|
+
dom === "ADS"
|
|
625
|
+
? { symbol_name: cfg.symbolName, value: val }
|
|
626
|
+
: dom === "GNV"
|
|
627
|
+
? { group: "ux", key: cfg.symbolName, value: val }
|
|
628
|
+
: { key: cfg.symbolName, value: val };
|
|
629
|
+
|
|
630
|
+
await invoke(cfg.domain, "write_value", mkPayload(true));
|
|
631
|
+
await sleep(300);
|
|
632
|
+
await invoke(cfg.domain, "write_value", mkPayload(false));
|
|
633
|
+
},
|
|
634
|
+
[tags, invoke]
|
|
635
|
+
);
|
|
636
|
+
|
|
637
|
+
/** Manual scale update (also writes to server if `serverTag` is present) */
|
|
638
|
+
const updateScale = useCallback(
|
|
639
|
+
async (scaleName: string, newScale: number, newLabel: string) => {
|
|
640
|
+
const cfg = scaleValues[scaleName];
|
|
641
|
+
if (!cfg) {
|
|
642
|
+
console.error(`Scale '${scaleName}' not found`);
|
|
643
|
+
return;
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
// If scale has a server tag, write to server first (GNV-style)
|
|
647
|
+
if (cfg.serverTag) {
|
|
648
|
+
await invoke(cfg.serverTag.domain, "write_value", {
|
|
649
|
+
group: "ux",
|
|
650
|
+
key: cfg.serverTag.symbolName,
|
|
651
|
+
value: { name: scaleName, scale: newScale, label: newLabel },
|
|
652
|
+
});
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
// Update local scale + recompute displays from raw
|
|
656
|
+
setScaleValues(prev => ({
|
|
657
|
+
...prev,
|
|
658
|
+
[scaleName]: { ...prev[scaleName], scale: newScale, label: newLabel },
|
|
659
|
+
}));
|
|
660
|
+
rescaleFromRaw(scaleName);
|
|
661
|
+
},
|
|
662
|
+
[scaleValues, invoke, rescaleFromRaw]
|
|
663
|
+
);
|
|
664
|
+
|
|
665
|
+
/** Derive initial display values from any seeded raw values (once scales are known) */
|
|
666
|
+
useEffect(() => {
|
|
667
|
+
// On mount or when scales change, recompute every numeric tag from raw
|
|
668
|
+
setValues(prev => {
|
|
669
|
+
const next = { ...prev };
|
|
670
|
+
for (const tag of tags) {
|
|
671
|
+
const raw = rawRef.current[tag.tagName];
|
|
672
|
+
if (raw === undefined) continue;
|
|
673
|
+
const disp = toDisplay(tag, raw);
|
|
674
|
+
if (next[tag.tagName] !== disp) next[tag.tagName] = disp;
|
|
675
|
+
}
|
|
676
|
+
return next;
|
|
677
|
+
});
|
|
678
|
+
}, [tags, toDisplay, scaleValues]);
|
|
679
|
+
|
|
680
|
+
const ctxValue = useMemo<BaseContextValue<VMapRuntime>>(
|
|
681
|
+
() => ({
|
|
682
|
+
values,
|
|
683
|
+
rawValues,
|
|
684
|
+
isLoading,
|
|
685
|
+
write,
|
|
686
|
+
tap,
|
|
687
|
+
scales: scaleValues,
|
|
688
|
+
updateScale,
|
|
689
|
+
}),
|
|
690
|
+
[values, rawValues, isLoading, write, tap, scaleValues, updateScale]
|
|
691
|
+
);
|
|
692
|
+
|
|
693
|
+
return (
|
|
694
|
+
<AutoCoreTagContext.Provider value={ctxValue}>
|
|
695
|
+
{children}
|
|
696
|
+
</AutoCoreTagContext.Provider>
|
|
697
|
+
);
|
|
698
|
+
};
|