Pythonic client for the Ellisys analyzer Remote Control automation API.
Project description
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).
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ellisys_analysis_automation-0.1.0.tar.gz.
File metadata
- Download URL: ellisys_analysis_automation-0.1.0.tar.gz
- Upload date:
- Size: 111.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
be92585acdc93a8640d8515404eeb6add24d86f88d417e0c3f653bf38a1101f6
|
|
| MD5 |
6d370e04138e26537640f506c6c4f43c
|
|
| BLAKE2b-256 |
a59b55ec53d54fdf7758e883611bc4f04340bac514195b553fddab3d3138a649
|
File details
Details for the file ellisys_analysis_automation-0.1.0-py3-none-any.whl.
File metadata
- Download URL: ellisys_analysis_automation-0.1.0-py3-none-any.whl
- Upload date:
- Size: 131.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
28625e4ecaa5e565a67856ce3e118609197b6294b57670f621a99fc5cf209ace
|
|
| MD5 |
b523143ca58752f0863e9506985b8a19
|
|
| BLAKE2b-256 |
6efd7f6efd27dfd7ab8312dbb351dd25c31eb38af864e9c23194e5c653fdc05f
|