From 9360dea6e6327004b905eb6d7c782cc7c0d3ba13 Mon Sep 17 00:00:00 2001 From: Christian Kolset Date: Wed, 29 Jul 2026 12:59:10 -0600 Subject: Hide non-writable channels from Controls picker, gate writes on enabled+writable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- ui/control_panel.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'ui/control_panel.py') 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: -- cgit v1.2.3