diff options
| author | Christian Kolset <ckolset@colostate.edu> | 2026-07-29 12:59:10 -0600 |
|---|---|---|
| committer | Christian Kolset <ckolset@colostate.edu> | 2026-07-29 12:59:10 -0600 |
| commit | 9360dea6e6327004b905eb6d7c782cc7c0d3ba13 (patch) | |
| tree | 54366e05a55f96cd4c676d71cfb2136d72392984 /ui | |
| parent | b407a079000f6a4b04ecf38eca17c57719e7a7ec (diff) | |
Hide non-writable channels from Controls picker, gate writes on enabled+writable
Adds ChannelConfig.writable so the Controls editor can only bind to
channels with a real write mapping (VS/MA/ME/MD/ST for CML, do*/DO for
digital I/O, write_cmd-configured SCPI channels, holding-register Modbus
channels) instead of read-only telemetry — this is exactly the class of
mistake hit earlier (binding a motor-speed control to M1_TV instead of
M1_VS). Also carries forward the enabled-channel gating for controls
(hide disabled channels from the picker, block writes to them at
_write() time) done alongside this investigation.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Diffstat (limited to 'ui')
| -rw-r--r-- | ui/control_editor.py | 6 | ||||
| -rw-r--r-- | ui/control_panel.py | 6 |
2 files changed, 10 insertions, 2 deletions
diff --git a/ui/control_editor.py b/ui/control_editor.py index 48de21d..5140bf3 100644 --- a/ui/control_editor.py +++ b/ui/control_editor.py @@ -360,8 +360,12 @@ class ControlEditorDialog(QDialog): dev = self.registry.get_instance(dev_id) if not dev: return - # Add actual channels + # Add actual channels (skip disabled — can't be driven while switched + # off — and skip read-only channels — a control writes, so a channel + # with no write mapping should never be offered as a target) for ch in dev.info.channels: + if not ch.enabled or not ch.writable: + continue self._ch_cb.addItem(f"{ch.channel_id} ({ch.name})", userData=ch.channel_id) # For Arduino backends also suggest digital pins for output diff --git a/ui/control_panel.py b/ui/control_panel.py index 2b936c4..22229ee 100644 --- a/ui/control_panel.py +++ b/ui/control_panel.py @@ -120,7 +120,11 @@ class ControlWidget(QFrame): if self.registry and self.device_id and self.channel_id: dev = self.registry.get_instance(self.device_id) if dev: - if dev.status not in (DeviceStatus.CONNECTED, DeviceStatus.SIMULATED): + ch = dev.get_channel(self.channel_id) + if ch is not None and not ch.enabled: + print(f"[Control] write_channel({self.channel_id}, {value}) skipped on " + f"{self.device_id} — channel is disabled") + elif dev.status not in (DeviceStatus.CONNECTED, DeviceStatus.SIMULATED): print(f"[Control] write_channel({self.channel_id}, {value}) skipped on " f"{self.device_id} — device status is {dev.status.value}, not connected") else: |
