ellisys_analysis_automation
A Pythonic client for the Ellisys analyzer Remote Control automation API (ZeroC Ice based). It hides the Ice machinery — connection setup, the Slice bindings, proxies, the communicator lifecycle — behind a small, typed API.
Install
python -m pip install -e . # from this folder (Sdk/Analysis/Python)
Requires CPython 3.12–3.14 and zeroc-ice~=3.8.2 (installed automatically). The bindings under
ellisys_analysis_automation/_generated/ are pre-generated with slice2py and are version-coupled
to that Ice runtime — regenerate them with Plugins\SliceAll.ps1 if the Ice version changes.
The SDK checks the installed Ice version at import and raises a clear error on a mismatch.
Documentation
- User guide + API reference — the Ellisys Analysis Automation SDK Guide (Python)
(Markdown/HTML/PDF), shipped in the Remote Control release archives: download
remote_api_analyzer.zip (generic /
Wi-Fi / WPAN / USB analyzers) or
bta_remote_api.zip (Bluetooth analyzers);
the guide is under
Sdk/Analysis/Python/. Its API reference is generated from this package's docstrings, sohelp(analyzer.<method>)always has the authoritative, version-true answer. - For AI agents —
llms.txt: a dense, single-file usage guide (mental model + the rules the bounded API enforces). Installed with the package; locate it viaimportlib.resources.files("ellisys_analysis_automation") / "llms.txt".
Usage
import ellisys_analysis_automation as ea
with ea.connect("localhost", 12345) as analyzer:
with analyzer.recording(save_to=r"C:\traces\session"): # path is on the analyzer machine
input("Recording... press Enter to stop & save")
Navigate the Overview tree through a scope that owns the item handles and frees them on exit. A trace can hold millions of items, so navigation is bounded by construction: you go through a cursor that yields one bounded page at a time — there is no way to accidentally pull everything.
from ellisys_analysis_automation import ItemField, MarkerColor
with ea.connect("localhost", 12345) as analyzer:
print(analyzer.overviews()) # ['BR/EDR Overview', 'Low Energy Overview', ...]
with analyzer.overview("BR/EDR Overview") as ov:
print(ov.root.child_count) # cheap count, even at millions
# Stream the whole tree in bounded, batched, page-released windows (safe at any size):
for item in ov.root.cursor().stream(): # ~256 items/round-trip; O(page) memory
print(item.time, item.description) # served from each page's prefetch cache
if done(item):
break # early break only fetched what you consumed
# Bounded materialize (raises BoundExceeded past 100k); records are handle-free:
first_50 = ov.root.cursor().take(50).records(ItemField.DESCRIPTION, ItemField.TIME)
# Full handle-free extract for CSV/pandas — constant memory, page-released:
for rec in ov.root.cursor().stream_records(ItemField.DESCRIPTION, ItemField.TIME):
write_csv(rec.position, rec.time_seconds, rec.description)
# Bounded search: glob/regex filters, finite default depth, observable progress:
for hit in ov.search_cursor(description=["*Paging*"]).stream():
hit.add_marker("found it", color=MarkerColor.RED) # select + mark in one call
Markers (annotate the trace):
from ellisys_analysis_automation import MarkerColor
analyzer.add_marker_at_time(6_391_402_625, "anomaly", color=MarkerColor.RED) # time in picoseconds
for m in analyzer.markers():
print(m.time, m.color.name, m.text)
Exports (output paths are on the analyzer machine):
import datetime
from ellisys_analysis_automation import ExportModes, BluetoothExportModes, BluetoothAudioOptions, BluetoothPacketLossMode
# Typed base modes:
analyzer.export_filtered_trace_time_range(
r"C:\out\first_5s.btt", max_duration_ps=datetime.timedelta(seconds=5), max_items=10_000)
analyzer.export_throughput(r"C:\out\tput.csv")
# Inspect the exact wire options offline before committing a long export:
print(analyzer.export_dry_run(r"C:\out\x", ExportModes.THROUGHPUT)) # [] (all server defaults)
# Any mode via the generic method + a typed carrier (or a raw {OptionName: value} mapping):
analyzer.export(r"C:\out\audio", BluetoothExportModes.AUDIO,
options=BluetoothAudioOptions(packet_loss=BluetoothPacketLossMode.SILENCE_SMOOTH))
A streaming cursor frees each page's handles by default (
release_mode="page"), keeping server memory atO(page_size). The trade: don't hold a liveOverviewItempast its page — snapshot it to anItemRecord(viarecords()/stream_records()), or usecursor(release_mode="defer")to retain handles for the scope.
Loading or recording? The overview grows while a trace loads or the analyzer records, so a full traversal (
stream/stream_records/walk/iter_children/materialize) raisesOverviewIncompleteinstead of silently stopping short. Either wait first (load(wait=True)/wait_until_loaded()), passfollow=Trueto tail items as they arrive (andbreakwhen your condition is met — handy during a live capture), orsnapshot=Truefor just what exists now. Bounded reads (take/page/cursor[a:b]) are exempt.
Session & trace files (load is blocking by default; paths are on the analyzer machine):
analyzer.load(r"C:\traces\capture.btt", timeout=300.0) # blocks until loaded (raises LoadTimeout)
info = analyzer.trace_file_info()
print(info.path, f"{info.file_size:,} bytes", info.data_source)
print(analyzer.app_info().version)
for task in analyzer.running_tasks():
print(task.name, task.progress) # progress is None when the server says it's N/A
if analyzer.is_modified:
analyzer.save_changes()
analyzer.close_trace_file()
Product facets expose product-specific operations — analyzer.bluetooth, analyzer.wifi,
analyzer.wpan, analyzer.usb30 — each raising NotAvailable if the connected analyzer isn't
that product (a combo analyzer may expose several):
from ellisys_analysis_automation import DeviceFilterMode, BluetoothPacketLossMode
bt = analyzer.bluetooth # cached; NotAvailable if not Bluetooth
for ch, s in enumerate(bt.channel_summaries()): # whole trace; index == RF channel
if s.total:
print(f"ch{ch}: ok={s.ok} err={s.errors} rate={s.error_rate:.1%}")
bt.configure_device_filter(DeviceFilterMode.KEEP_INVOLVING, [0x001122334455, 0xAABBCCDDEEFF])
bt.export_audio(r"C:\out\audio", packet_loss=BluetoothPacketLossMode.SILENCE_SMOOTH) # via Export (bluetooth_audio)
Errors are Pythonic exceptions (ConnectionFailed, OperationError, ScopeClosed for a handle
used after its scope/page released it, and BoundExceeded when a materialize exceeds its cap).
No ZeroC Ice type crosses the API; the per-item escape hatches are item.handle /
items.handles (raw server handles).
Status
- Connection + recording lifecycle —
connect(),recording(), start/stop/abort. - Overview navigation — scoped, bounded-by-construction cursors over the tree and over
search, batch-by-default pages, and handle-free
ItemRecordsnapshots. - Markers — typed
MarkerColor, add at a time / on the selected (or any) overview item, and read all markers back as handle-freeMarkers. - Exports — generic
export()+ typed wrappers for the base modes, typed option carriers (with aBluetoothPacketLossModeenum), an offlineexport_dry_run(), and a raw-mapping escape hatch for any current/future mode. - Session / trace files / info — blocking
load()(+start_loading/is_loading/wait_until_loaded),trace_file_info()/app_info()/recording_status()typed results, data sources,save_changes/close_trace_file,insert_message, running tasks, and an opaque settings round-trip. - Product facets —
analyzer.bluetooth(channel summaries, spectrum RSSI, device filter, link keys, "save & continue", typed Bluetooth exports),analyzer.wifi(Wi-Fi keys, device filter),analyzer.wpan(Thread/Zigbee key management),analyzer.usb30(link control, packet/symbol save). Each raisesNotAvailableif the connected analyzer isn't that product. - Logic signals —
logic_signals_state()(level bitmask at a time) andfind_logic_signal_transition()(masked edge search).
The SDK now wraps the analyzer Remote Control API — every operation except the deprecated
InsertComment and the legacy ExportAudio (superseded by the bluetooth_audio export mode).
Release files for ellisys-analysis-automation 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| ellisys_analysis_automation-0.1.0.tar.gz | 111.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| ellisys_analysis_automation-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 242.7 kB
Release files / ellisys_analysis_automation-0.1.0.tar.gz
| Download URL | ellisys_analysis_automation-0.1.0.tar.gz |
|---|---|
| Size | 111.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
be92585acdc93a8640d8515404eeb6add24d86f88d417e0c3f653bf38a1101f6
|
|
BLAKE2b-256 checksum How to use checksums |
a59b55ec53d54fdf7758e883611bc4f04340bac514195b553fddab3d3138a649
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.0
|
Release files / ellisys_analysis_automation-0.1.0-py3-none-any.whl
| Download URL | ellisys_analysis_automation-0.1.0-py3-none-any.whl |
|---|---|
| Size | 131.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
28625e4ecaa5e565a67856ce3e118609197b6294b57670f621a99fc5cf209ace
|
|
BLAKE2b-256 checksum How to use checksums |
6efd7f6efd27dfd7ab8312dbb351dd25c31eb38af864e9c23194e5c653fdc05f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.0
|