| Age | Commit message (Collapse) | Author |
|
Device tab stays hardware-only (pins, wiring, may vary per workstation);
the Channels window owns the profile-facing identity. Concretely:
- Fix a real regression: SerialDevice generic-format Apply & Reconnect
nulled out custom channel_names/units every time (no fallback, unlike
every other optional field in reconfigure()), silently reverting to
sig0/sig1/... ids.
- Plot legend now live-tracks the current Signal/Channel name instead of
freezing tr.label at add-time, so a rename shows up without re-adding
the trace.
- Add an inline quick-reconnect (combo + button, pre-selects the actual
current source) directly on each Channel block in the Channels window,
for the common single-source case — rewiring hardware no longer means
touching every Plot/pipeline that referenced it.
- Collapse the Channel ID field behind an "ID ▸" advanced toggle;
channel_id is already auto-derived from the name (_slug_id) and rarely
needs to be seen.
- Devices tab's Signal "Name" column relabeled "Label" with a tooltip —
de-emphasized now that Channel name is the real identity.
- Move "create a Channel from this Signal" from a column on the Devices
tab's signal table to a ⊕ button on each Signal row in the Channels
tab's Namespace panel — the action now lives where the identity is
created, not on the hardware tab. Only that instance opts in
(on_create_channel); the read-only Namespace dock on the main window
is unaffected.
- Floor the Namespace panel's width at its columns' natural size so
dragging the Channels-tab splitter narrower can't push the ⊕ column
behind the horizontal scrollbar.
- Breadcrumb log when a profile-saved Signal override can't be applied
because the signal_id no longer exists.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
|
Apply & Reconnect rebuilt a device's whole Signal list from hardware
defaults on every call, silently discarding user/profile-set names,
units, and colors even when pins hadn't changed. Add
merge_signal_metadata() and call it from ArduinoDevice.remap_pins()
and SerialDevice.reconfigure() to reapply the same fields
ProfileManager already treats as user overrides, keyed by signal_id.
Also close a related gap: removing a pin that a Channel/Plot/Control
still referenced left it silently dangling, and SignalProcessor never
pruned its latest-value cache, so a derived Channel kept computing off
a permanently frozen stale reading. Add SignalProcessor.
on_device_reconfigured() to purge that cache, reference_registry.
find_references() for a console breadcrumb, and live "missing source"
indicators on Plot traces and Channel blocks reusing ControlWidget's
existing stale/QSS pattern. Also fixes ControlWidget._write() still
enqueuing writes to a channel that no longer exists.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
|
Arduino analog Signal ids used to be the pin name itself, so fixing a
wrong pin silently changed the id and orphaned any plot trace, control,
or filter pipeline pointing at it. Analog Signal ids are now positional
(ai0, ai1, ...) and decoupled from the underlying pin, matching how
digital I/O already worked.
More broadly, formalizes a Device -> Signal -> Channel -> Plot naming
model (SignalConfig for physical device channels, Channel for derived/
computed ones) and adds core/reference_registry.py to propagate any
Signal or Channel id rename through plot traces, controls, and filter
pipelines instead of leaving them dangling. Signal ids are now editable
in the Signals tab with the same propagation.
.labui profile schema bumped to v2.0 with a transparent migration for
old files, including remapping old pin-name Signal ids to the new
positional ones. Removed six confirmed-dead files (two legacy device
classes, four superseded top-level ui/ duplicates).
|
|
machine
COM/tty numbers aren't stable across machines or replugs. Devices now save
their USB serial number and OS description alongside the port; on profile
load, if the saved port isn't present, ArduinoLayer.find_port_by_identity()
looks for a match and remaps it. Falls back to the saved port (device shows
ERROR) if nothing matches.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
|
|
|
Devices: auto-name from OS-reported port description (Device Manager /
udev string) instead of a generic label; default Serial #Channels 1;
consistent simulate-mode checkbox across backends; inline device rename.
Channels: calibration/filters move out of Signals into a Channel
"Operation" (adds Scale/Offset alongside the existing math kinds);
single-physical-source Channels get an embedded Filters block; new
Channels auto-name/auto-ID from their source and reject duplicate
names/IDs on apply; "Create Channel" button on each Signal row; renamed
"Sources" -> "Signals" in the Channels UI; Signals' READ/WRITE dir badge
(was silently-broken IN/OUT) now reflects the real writable flag.
Plot: default layout is one pane per Channel (not per device, not raw
Signals) titled by channel name; "+ Add Channel" is a checkbox dialog
instead of an inline dropdown; traces get up/down reorder; live unit
changes (e.g. a Mark-10 gauge switching lb/kgF/N/ozF) propagate to an
open pane's axis label without clobbering a manually-typed one.
Control Panel: hardware assignment now picks from the same writable-
Signals list instead of a separate device/channel combo with a
hardcoded Arduino pin list; stale visual indicator when a control's
target device/channel disconnects or disappears; documented the `vars`
bridge (Control Panel On Action Script <-> Channel scripts) in both
directions' help text and script templates.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
|
# Conflicts:
# ui/control_editor.py
|
|
|
|
|
|
New Settings > General > "Developer mode" checkbox (default on, so
this repo's simulate-by-default workflow is unaffected out of the box)
persisted through the existing core/app_settings.py load/save
functions. Exposed to code that can't easily receive the settings dict
via core.app_settings.is_developer_mode()/set_developer_mode(), a
small in-memory cache MainWindow keeps in sync whenever settings are
loaded or applied.
Debug window (ui/windows/debug_window.py): minimal first pass per the
plan — a live console. core/debug_log.py tees stdout/stderr into a
ring buffer + Qt signal (installed once in main.py, before anything
prints), so the window shows everything printed since app start,
including from background poll threads, not just what's printed while
it happens to be open. Its toolbar button is hidden unless developer
mode is on.
Simulate gating: every device's Simulation Mode checkbox/dropdown is
now hidden when developer mode is off — ui/add_device_dialog.py (also
covers the motion_capture camera panel, which shares this same
checkbox rather than having its own), and the per-device config
widgets in analog_input.py, arduino_device.py, digital_io.py,
nidaqmx_device.py, serial_device.py. Hiding rather than force-clearing
an already-simulating device's state — an existing simulated device
keeps working if developer mode is turned off later; the option is
just not offered again until it's back on.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
|
Mark10Layer._parse() already tracked whichever unit suffix the gauge
last reported (lb/kgF/N/ozF — the gauge's physical unit button cycles
these independently of this app). serial_device.py hardcoded the
"force" channel's unit to "N" and never updated it, so switching units
on the gauge itself was invisible here.
Adds Mark10Layer.current_unit and has SerialDevice.read_channels()
keep the "force" ChannelConfig's unit in sync with it on every poll.
This fixes the unit shown in anything that reads ChannelConfig.unit
live — new plots, channel pickers, CSV log headers — but does not
relabel the Y-axis of an already-open plot pane, since plot axis
labels are baked into PlotConfig.y_label once at plot-build time, not
re-read from the channel live. Making an open pane's axis relabel
itself would need new signal plumbing from the device through
AcquisitionEngine to the strip chart — a bigger, separate change.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
|
DeviceInfo.name existed but was hardcoded per device type and never
operator-editable. Adds a Display Name field to Add Device and makes
the Info-tab Name field in the device config dialog editable, and
threads the name through get_save_config()/ProfileManager.apply() so
a custom name survives a .labdaq save/reload instead of reverting to
the type default. Name is applied post-construction rather than as a
constructor kwarg, since no device factory declares a "name" param.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
|
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>
|
|
motion_capture setting to false
|
|
communication
|
|
|
|
|
|
Naming conventions:
- Devices window: "Channel ID" column → "Signal ID"
- Serial device auto-gen IDs: CH# → sig# (generic, SCPI, Modbus fallbacks)
- Channels window physical section: "Physical Channels" → "Signals"
- Channels window virtual section: "Virtual Channels" → "Channels"
- "Add Virtual" button → "Add Channel"
- New derived channel default name: "Virtual Channel #" → "Channel #"
Signals panel (ChannelPipelineBlock):
- Remove Calibrate header button; add inline Calibration section in body
- Remove Math section (Derivative/Integral) entirely
- scale_offset excluded from filter dropdown; routed to Calibration section
- Existing pipelines: scale_offset loads into Calibration, math filters dropped
- _FILTER_KEYS excludes derivative, integral, scale_offset
Splitter default position:
- Left (Signals) pane initialised to minimum content width via QTimer.singleShot
- setStretchFactor(0,0) / (1,1): left stays narrow, right grows on resize
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Add Device dialog:
- Replace Available Devices QGroupBox with plain devWindowTitle label
to match Configuration section style — no box/border
- Auto-scan on open via QTimer.singleShot(0)
- Rename Scan All → Refresh
Serial config widget:
- Fix gap between protocol panel and Available Serial Ports: introduce
_AdaptiveStack (QStackedWidget subclass) that reports only the current
panel's sizeHint; set Fixed vertical size policy so the stack never
expands beyond its content regardless of window size
- Stretch added between Available Serial Ports and Apply & Reconnect so
the button stays pinned to the bottom
- Rename Channels → Signals in _GenericPanel and _SCPIPanel (Signal Queries)
Config dialog (device info tab):
- Rename Channels → Signals
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
|
|
|
|
|
|
|