- Populate prop elements with manifest default values when adding
components in both offline and live mode
- Send config values from manifest in SOX add command for live devices
- Refresh button in properties panel now fetches fresh values from
the connected device before re-reading the DOM
- Properties panel fetches device values on open in live mode
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fix add component from palette in live mode: resolve <app> element
as comp_id 0, fix type_id lookup to use type_name_map, set type_name
on newly added SoxComponent, sync device values into DOM after add,
write meta position back to device, and subscribe new component to COV.
Fix delete component in live mode: clean up subscriptions for deleted
component and all its descendants.
Add tree root context menu with device app actions (save, hibernate,
quit, restart, reboot) in live mode. Device save clears dirty state.
Clean up connection lost handling to do a full disconnect.
Fix slot registry to copy base slots and renumber IDs correctly.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Authentication failures now show "check username and password", busy
devices say "device is busy", etc.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Discover dialog shows a device list with Port, Wait Time fields and a
Discover button. Selecting a device and clicking Connect (or double-
clicking) opens a credentials prompt for username/password, then
connects. The Connect dialog is reverted to its original simple form.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Send DISCOVER broadcast (type 0) to 255.255.255.255 and the Sedona
multicast address 239.255.18.76 to find devices on the network.
Responses are listed in a Treeview showing IP and platform ID.
Selecting a device fills the Host field; double-click connects.
Wait time is configurable (default 10s, range 1-60s).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The dispatch check compared the raw hostname string against the UDP
source IP, silently dropping responses when they differed (e.g.
"localhost" vs "127.0.0.1"). Resolve hostname to IP at session init.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
In live mode the DOM is rebuilt from the device when switching sheets,
creating new element objects. The pending link from the old tree could
not be found by identity in canvas_link_map. Re-resolve it by from/to
attributes after the rebuild so the selection matches.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
_slot_name_by_id() now resolves SOX link slot IDs against the
inheritance-flattened final_components_registry instead of the
per-type slot_registry whose local IDs were wrong for types with
intermediate parents (e.g. RegFloat→Register→Component). This
produced incorrect link endpoints, inflated linked-slot visibility,
and different box sizes between file and live modes.
Also: tighten routing constants for denser wiring, add wiresheet
PNG print/export (Ctrl+P), sort link routing jobs by gap distance,
remove debug route logging, and fix live tree-expand re-selection.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Slots with no flags (sensor, controlSignal, out_*) were not skipped
during config property reads, consuming bytes that the device never
sent and misaligning every subsequent config value (setpoint,
proportionalBand, etc.) into tiny denormalized floats like 2.36875e-41.
Changed the filter in _apply_props from "skip if runtime" to "skip if
not config" so only explicitly config-flagged slots are read from config
messages. Also switched iter("slot") to findall("slot") in the slot
registry builder to avoid picking up nested descendants.
Float display now defaults to 2 decimal places everywhere (wiresheet
and properties panel), honouring the precision facet when one exists.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds _fmt_float() helper that formats 32-bit floats with :.6g precision
but appends .0 when the result has no decimal point, matching Niagara
and .sax file display conventions (e.g. 175.0 not 175, 0.0 not 0).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sox reads 32-bit floats that Python promotes to 64-bit doubles, producing
display artifacts like 22.011558532714844. Using :.6g format gives clean
values matching .sax file precision (22.0116, -19.9574, 175, 14).
Applied to both initial DOM build and COV update paths.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Opening a file while connected to a device prompts to disconnect first.
Connecting to a device while a file is open prompts to save unsaved
changes, then closes the file before showing the connect dialog.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Build root children directly under <app> instead of wrapping them in
a <comp name="app"> element. This matches the .sax DOM structure
where <app> is the container, so component paths like /AHU/TmpCont/X
match between link references and get_component_path.
- Fix _comp_path to produce /AHU/TmpCont/X format (skip root id 0,
leading /) matching the .sax link path convention.
- Format float property values to 4 decimal places instead of full
Python float precision (22.0116 vs 22.011558532714844).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add type_name_map on SoxClient so components loaded after connect
resolve proper names (e.g. control::And2) instead of kit::typeN.
This lets the slot registry and final_components_registry match,
so component boxes show their slots and property values.
- Load live schema gracefully: skip missing kit manifests instead of
aborting, compile the kits we have, and warn about missing ones in
the status bar.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Three fixes so live wiresheets render identically to offline .sax files:
1. Inherit sys::Component base slots (meta) into every type's slot
registry so component x/y positions are read from the device.
2. Place <link> elements under a <links> container element instead of
directly under <app>, matching the .sax structure that draw_links
and build_linked_slot_index expect.
3. Deduplicate links (each link appears on both endpoints in Sox) so
wires are not drawn twice.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Swap Connect/Cancel button order so Connect is the default (leftmost).
Guard background thread against cancelled state so a cancelled connect
does not leave the app in live mode. Cancel during connection now
disconnects the session cleanly in a cleanup thread.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
On connect, also loads root's immediate children so the first tree level
shows real names. For deeper levels, inserts placeholder <comp> elements
for uncached children so the Treeview shows + expand arrows for folders
that have children on the device.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
_on_tree_open used tree.selection() which may differ from the opened
node; switched to tree.focus(). Network calls in _live_tree_expand now
run in a daemon thread so the UI stays responsive during lazy loading.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
After open_wiresheet rebuilds the DOM and tree, re-find the target
element by its comp id (not the old tree item ID which no longer
exists) and re-select it with the restoring flag to prevent recursion.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Use RLock instead of Lock for _close_lock so close() can call
_shutdown() without deadlocking — previously the session never
marked itself closed, causing infinite keepalive sends.
Mask kit checksums to unsigned 32-bit for hex display so negative
i4 values render as proper 8-digit hex (e.g. d3984c51 not -2c67b3af).
Tested against live device at 192.168.1.251 — full handshake,
schema read, and component tree load confirmed working.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New checkbox in Preferences (default off). When enabled, every DASP
send (>>>) and receive (<<<) prints message type, seq/ack numbers,
payload size, and remote address to stdout.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Guard tree.get_children() with tree.exists() so a stale item ID from
a COV or lazy-load rebuild does not raise TclError.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Port the DASP transport and Sox protocol stack from sedonaOntrol Java
to Python, enabling live device editing alongside the existing offline
SAX editor. Lazy-loads components on navigation, caches them, and
subscribes to COV events for the active wiresheet.
New files: dasp.py, sox.py, device_session.py, connect_dialog.py,
live_hooks.py. Modified: app_state.py (live-mode state), main.py
(Device menu, COV polling, lazy tree expand), properties.py (Sox
write-through), sax_file.py (structural mutations route through
live_hooks), schema.py (find_manifest helper).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Scan sedona/platforms/db/ to find which native kits are compiled for
the SAX's platform. Kits with native code for other platforms, kits
providing a PlatformService for a different device, and their
transitive dependents are placed in a "Not supported" section with a
red-cross checkbox that cannot be toggled.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The save dialog now suggests e.g. normal_kits_20260911_143200.xlsx
so successive exports never collide.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Saves the kit table to an Excel file with section headers, check
marks, and all four data columns. Default filename is based on the
open SAX file.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Renamed "Kits to be installed" to "Kits available on the computer"
for kits whose dependencies are all in the app. Kits with unmet
dependencies go into a greyed-out "Other kits on the computer" section
that cannot be selected or ticked.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
No columns stretch — sizes are set for the longest kit name
(ontrolModbusTcpSlaveSmart) and action text (Keep with no checksum).
A horizontal scrollbar appears when the pane is narrower than the
total column width.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The boxes dict was missing the (False, False) key — an unchecked kit
that is also required — which caused a KeyError when the Kit Manager
opened automatically for files with incomplete checksums.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When a SAX file is opened and any declared kit is missing a checksum,
the Kit Manager panel opens automatically and the palette stays empty
until the checksums are resolved.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The sidebar palette combo now lists kits from the open file's schema
rather than every kit installed in Sedona home, with their resolved
version labels. Falls back to all installed kits when no file is open.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Manage Kits now opens inside the editor pane (like Properties and Link
View) instead of a separate Toplevel window. Also normalize hex
checksums by stripping leading zeros so .kit and manifest filenames
that disagree on padding (e.g. 462d43e vs 0462d43e) still resolve to
a version.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Opening a Properties or Link view was invisible to the history, so Back
from one did two things at once: it took the panel down and stepped to the
sheet before the one it was opened over. There was no way back to a
picture you had just been reading.
A history entry is now a (kind, element) pair naming what the editor pane
held -- a sheet, a Properties view, or a Link View -- and restoring one
puts that back: a sheet entry selects its tree node, a panel entry
re-opens the panel. So opening a panel is a move like opening a sheet.
Back from a Properties view lands on whatever came before it and Forward
brings the panel back, and following a link out of the Link View now has a
way home: Back returns to the picture the link was followed from, and a
second Back to the sheet that was open before that.
The panel's own Close is deliberately not recorded. It means "leave this
view", and recording it would put a sheet entry after the panel's, so Back
would re-open the panel that had just been closed. Leaving the position
alone means Back steps to what came before the panel and Forward re-opens
it, which is what the arrows are for.
Both arrows still go through close_editor_panel first, so unsaved
Properties edits are asked about exactly as before and a refusal leaves
the view and the position where they were. Pruning now has two kinds of
entry to check -- a sheet needs a tree node, a panel needs its component
still in the document -- and collapses any pair it leaves naming the same
view, since a Back that visibly does nothing is worse than a shorter
trail.
sheet_history and its functions are renamed for what they now hold.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>