summaryrefslogtreecommitdiff
path: root/api_layers/protocols/mark10.py
diff options
context:
space:
mode:
authorChristian Kolset <christian.kolset@gmail.com>2026-08-02 01:34:43 -0600
committerChristian Kolset <christian.kolset@gmail.com>2026-08-02 01:34:43 -0600
commita3aa1df99df8f413cac2ba6020b7cd0dec6d2390 (patch)
treea4c5feca6b0db326d9e54f417abc132c1270a7a3 /api_layers/protocols/mark10.py
parentf5066a8ca2fb50aa3dddf2c8847e52574cdde6ad (diff)
parentf1aaffbc3eb1e2c154315c556d2555803eea7997 (diff)
Merge origin/main: reconcile ConfigWindow consolidation with Debug window + protocol updates
origin/main (23 commits) added a Debug window/log system on top of the old separate Devices/Channels/Plot windows, plus protocol fixes (cml, mark10, modbus_rtu, scpi) and device/profile changes. Local main (3 commits) replaced the separate windows with a unified ConfigWindow + dock panel. Kept local's ConfigWindow/dock architecture and ported the Debug window onto it: new toolbar button + _open_debug(), gated by developer_mode same as origin's version. Deduped the two independent "developer mode" toggles that had collided in SettingsWindow (origin's General-tab checkbox gating Debug window + device sim-mode visibility, local's Advanced-tab checkbox setting verbose logging) into one General-tab checkbox that does both. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Diffstat (limited to 'api_layers/protocols/mark10.py')
-rw-r--r--api_layers/protocols/mark10.py32
1 files changed, 26 insertions, 6 deletions
diff --git a/api_layers/protocols/mark10.py b/api_layers/protocols/mark10.py
index 1b5bf1c..48ed927 100644
--- a/api_layers/protocols/mark10.py
+++ b/api_layers/protocols/mark10.py
@@ -10,6 +10,11 @@ Commands (sent with CR terminator):
Response format: "+0.1234 kgF" (sign, value, space, unit suffix)
+Replies are read up to CR with Serial.read_until(b"\\r") rather than
+readline(), since pyserial's readline() looks for LF by default and the
+gauge only terminates with CR — readline() would otherwise block for the
+full serial timeout on every poll.
+
Channels exposed:
force — current force reading (in instrument's selected unit)
unit_code — numeric index into UNITS list (lb=0, kgF=1, N=2, ozF=3)
@@ -39,12 +44,20 @@ class Mark10Layer(BaseProtocol):
super().__init__(port, baud, poll_interval, simulate)
self._unit = "N"
+ @property
+ def current_unit(self) -> str:
+ """Last unit suffix seen in a gauge reply (e.g. "N", "kgF")."""
+ return self._unit
+
# ── Protocol ──────────────────────────────────────────────────────────
def _poll(self) -> Dict[str, float]:
try:
- self._ser.write(b"?\r")
- resp = self._ser.readline().decode(errors="replace").strip()
+ with self._io_lock:
+ self._ser.reset_input_buffer()
+ self._ser.write(b"?\r")
+ self._ser.flush()
+ resp = self._ser.read_until(b"\r").decode(errors="replace").strip()
return self._parse(resp)
except Exception:
return {}
@@ -76,10 +89,15 @@ class Mark10Layer(BaseProtocol):
"cycle_units": b"U\r",
}
cmd = cmd_map.get(channel_id)
- if cmd is None or not self._ser:
+ if cmd is None:
+ return False
+ if self.simulate:
+ return True
+ if not self._ser:
return False
try:
- self._ser.write(cmd)
+ with self._io_lock:
+ self._ser.write(cmd)
return True
except Exception:
return False
@@ -88,8 +106,10 @@ class Mark10Layer(BaseProtocol):
def zero(self) -> None:
if self._ser:
- self._ser.write(b"Z\r")
+ with self._io_lock:
+ self._ser.write(b"Z\r")
def cycle_units(self) -> None:
if self._ser:
- self._ser.write(b"U\r")
+ with self._io_lock:
+ self._ser.write(b"U\r")