summaryrefslogtreecommitdiff
path: root/devices
diff options
context:
space:
mode:
Diffstat (limited to 'devices')
-rw-r--r--devices/serial_device.py45
1 files changed, 37 insertions, 8 deletions
diff --git a/devices/serial_device.py b/devices/serial_device.py
index 458aec8..067656a 100644
--- a/devices/serial_device.py
+++ b/devices/serial_device.py
@@ -142,7 +142,10 @@ class SerialDevice(BaseDevice):
raw = self._layer.read()
if not raw:
return {}
- # Protocol layers already use channel_id keys — pass through.
+ if self._fmt not in _GENERIC_FORMATS:
+ # Protocol layers already key by channel_id — pass through untouched.
+ # (Write-only channels, e.g. CML "M1_VS", never appear in raw — correctly dropped.)
+ return raw
# Generic (ArduinoLayer) may use arbitrary names — remap by position.
mapped: Dict[str, float] = {}
raw_vals = list(raw.values())
@@ -154,6 +157,8 @@ class SerialDevice(BaseDevice):
return mapped
def write_channel(self, channel_id: str, value: Any) -> bool:
+ if self.status not in (DeviceStatus.CONNECTED, DeviceStatus.SIMULATED):
+ return False
return self._layer.write(channel_id, int(value))
def get_config_widget(self) -> QWidget:
@@ -276,16 +281,20 @@ class SerialDevice(BaseDevice):
elif fmt == "mark10":
from api_layers.protocols.mark10 import UNITS as _MARK10_UNITS
return [
- ChannelConfig("force", "Force", "N", -5000.0, 5000.0, color=_COLORS[0]),
- ChannelConfig("unit_code", "Unit Code", "", 0.0, float(len(_MARK10_UNITS) - 1), color=_COLORS[1]),
+ ChannelConfig("force", "Force", "N", -5000.0, 5000.0, color=_COLORS[0]),
+ ChannelConfig("unit_code", "Unit Code", "", 0.0, float(len(_MARK10_UNITS) - 1), color=_COLORS[1]),
+ # Write-only action channels (no reading — for control buttons)
+ ChannelConfig("zero", "Zero Gauge", "", 0.0, 1.0, color=_COLORS[2]),
+ ChannelConfig("cycle_units", "Cycle Units", "", 0.0, 1.0, color=_COLORS[3]),
]
elif fmt == "cml":
_CMD_UNITS = {"TP": "counts", "TV": "counts/s", "TC": "%×10", "TS": "flags"}
+ _WRITE_UNITS = {"VS": "counts/s", "MA": "counts"}
channels = []
color_idx = 0
for motor in self._motors:
+ mid = motor.get("motor_id", "M1")
for cmd in motor.get("read_cmds", ["TP", "TV", "TC"]):
- mid = motor.get("motor_id", "M1")
channels.append(ChannelConfig(
channel_id=f"{mid}_{cmd}",
name=f"{mid} {cmd}",
@@ -294,6 +303,26 @@ class SerialDevice(BaseDevice):
color=_COLORS[color_idx % len(_COLORS)],
))
color_idx += 1
+ # Write-only setpoint channels (no reading — for control widgets)
+ for cmd in ("VS", "MA"):
+ channels.append(ChannelConfig(
+ channel_id=f"{mid}_{cmd}",
+ name=f"{mid} {cmd}",
+ unit=_WRITE_UNITS.get(cmd, ""),
+ min_value=-1e6, max_value=1e6,
+ color=_COLORS[color_idx % len(_COLORS)],
+ ))
+ color_idx += 1
+ # Write-only action channels — motor must be enabled (ME) before VS/MA take effect
+ for cmd, label in (("ME", "Enable"), ("MD", "Disable"), ("ST", "Stop")):
+ channels.append(ChannelConfig(
+ channel_id=f"{mid}_{cmd}",
+ name=f"{mid} {label}",
+ unit="",
+ min_value=0.0, max_value=1.0,
+ color=_COLORS[color_idx % len(_COLORS)],
+ ))
+ color_idx += 1
return channels or [ChannelConfig("M1_TP", "M1 TP", "counts", color=_COLORS[0])]
return []
@@ -793,7 +822,7 @@ class _CMLPanel(QWidget):
lay.setContentsMargins(0, 4, 0, 4)
lay.setSpacing(6)
- grp = QGroupBox("Motors (RS-232: addr=0 / RS-485: addr 1-31)")
+ grp = QGroupBox("Motors (motor ID 1-31, always sent explicitly)")
grp_lay = QVBoxLayout(grp)
scroll = QScrollArea()
@@ -856,9 +885,9 @@ class _MotorRow(QWidget):
lay.addWidget(self._id_edit)
self._addr_spin = QSpinBox()
- self._addr_spin.setRange(0, 31)
- self._addr_spin.setValue(m.get("address", 1))
- self._addr_spin.setToolTip("0 = RS-232 (no prefix), 1-31 = RS-485")
+ self._addr_spin.setRange(1, 31)
+ self._addr_spin.setValue(max(1, m.get("address", 1)))
+ self._addr_spin.setToolTip("CM1-C motor ID — always sent explicitly as \".<id>\"")
lay.addWidget(QLabel("Addr:"))
lay.addWidget(self._addr_spin)