Loading noctua/guider.py +11 −2 Original line number Diff line number Diff line Loading @@ -45,6 +45,7 @@ class Guider: self._task = None self._stick_target = None self._last_frame_time = None self.once = False self.ao_pos = [50.0, 50.0] self.ao_offload_threshold = 90 Loading Loading @@ -95,6 +96,10 @@ class Guider: if params: self.configure(params) # "once" is a start-time mode switch, not a persistent config field # (unlike configure()'s keys) — always resolved fresh so a prior # one-shot run can't silently leak into a later continuous Guide. self.once = bool(params.get("once", False)) if params else False if self._task and not self._task.done(): return Loading Loading @@ -137,8 +142,12 @@ class Guider: msg = f"step error: {e}" log.error(f"Guider: {msg}") self.error.append(msg) # Set self.active to False to test one-shot # self.active = False if self.once: self.active = False break # No fixed delay: _step()/_acquire() already block on the camera # producing a new frame, so the next correction starts as soon # as it is. The sleep(0) just yields control for cancellation. await asyncio.sleep(0) def _step(self): Loading noctua/web/pages/macros/control_panel.html +2 −0 Original line number Diff line number Diff line Loading @@ -227,6 +227,8 @@ <div class="input-group input-group-sm"> <button class="btn btn-outline-secondary" id="btn-{{ panel_id }}-pick" type="button">Pick</button> <button class="btn btn-outline-primary" type="button" id="btn-{{ panel_id }}-once">Once</button> <button class="btn btn-primary flex-fill" type="button" id="btn-{{ panel_id }}-guide-start" {% if fixed %} Loading noctua/web/static/js/guider-panel.js +2 −0 Original line number Diff line number Diff line Loading @@ -476,6 +476,7 @@ function initPanel(panelId) { const cameraEl = document.getElementById(`guider-camera-${panelId}`); const targetEl = document.getElementById(`guider-target-${panelId}`); const guideBtn = document.getElementById(`btn-${panelId}-guide-start`); const onceBtn = document.getElementById(`btn-${panelId}-once`); const cxEl = document.getElementById(`guider-cx-${panelId}`); const cyEl = document.getElementById(`guider-cy-${panelId}`); Loading @@ -497,6 +498,7 @@ function initPanel(panelId) { cameraEl?.addEventListener('change', () => onTargetChange(panelId, targetEl?.value ?? 'center')); targetEl?.addEventListener('change', e => onTargetChange(panelId, e.target.value)); guideBtn?.addEventListener('click', () => postGuider(guideBtn, collectParams(panelId))); onceBtn?.addEventListener('click', () => postGuider(onceBtn, { ...collectParams(panelId), once: true })); if (guideBtn) { document.addEventListener('noctua-telemetry', e => { Loading Loading
noctua/guider.py +11 −2 Original line number Diff line number Diff line Loading @@ -45,6 +45,7 @@ class Guider: self._task = None self._stick_target = None self._last_frame_time = None self.once = False self.ao_pos = [50.0, 50.0] self.ao_offload_threshold = 90 Loading Loading @@ -95,6 +96,10 @@ class Guider: if params: self.configure(params) # "once" is a start-time mode switch, not a persistent config field # (unlike configure()'s keys) — always resolved fresh so a prior # one-shot run can't silently leak into a later continuous Guide. self.once = bool(params.get("once", False)) if params else False if self._task and not self._task.done(): return Loading Loading @@ -137,8 +142,12 @@ class Guider: msg = f"step error: {e}" log.error(f"Guider: {msg}") self.error.append(msg) # Set self.active to False to test one-shot # self.active = False if self.once: self.active = False break # No fixed delay: _step()/_acquire() already block on the camera # producing a new frame, so the next correction starts as soon # as it is. The sleep(0) just yields control for cancellation. await asyncio.sleep(0) def _step(self): Loading
noctua/web/pages/macros/control_panel.html +2 −0 Original line number Diff line number Diff line Loading @@ -227,6 +227,8 @@ <div class="input-group input-group-sm"> <button class="btn btn-outline-secondary" id="btn-{{ panel_id }}-pick" type="button">Pick</button> <button class="btn btn-outline-primary" type="button" id="btn-{{ panel_id }}-once">Once</button> <button class="btn btn-primary flex-fill" type="button" id="btn-{{ panel_id }}-guide-start" {% if fixed %} Loading
noctua/web/static/js/guider-panel.js +2 −0 Original line number Diff line number Diff line Loading @@ -476,6 +476,7 @@ function initPanel(panelId) { const cameraEl = document.getElementById(`guider-camera-${panelId}`); const targetEl = document.getElementById(`guider-target-${panelId}`); const guideBtn = document.getElementById(`btn-${panelId}-guide-start`); const onceBtn = document.getElementById(`btn-${panelId}-once`); const cxEl = document.getElementById(`guider-cx-${panelId}`); const cyEl = document.getElementById(`guider-cy-${panelId}`); Loading @@ -497,6 +498,7 @@ function initPanel(panelId) { cameraEl?.addEventListener('change', () => onTargetChange(panelId, targetEl?.value ?? 'center')); targetEl?.addEventListener('change', e => onTargetChange(panelId, e.target.value)); guideBtn?.addEventListener('click', () => postGuider(guideBtn, collectParams(panelId))); onceBtn?.addEventListener('click', () => postGuider(onceBtn, { ...collectParams(panelId), once: true })); if (guideBtn) { document.addEventListener('noctua-telemetry', e => { Loading