Skip to main content

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, so help(analyzer.<method>) always has the authoritative, version-true answer.
  • For AI agentsllms.txt: a dense, single-file usage guide (mental model + the rules the bounded API enforces). Installed with the package; locate it via importlib.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 at O(page_size). The trade: don't hold a live OverviewItem past its page — snapshot it to an ItemRecord (via records()/stream_records()), or use cursor(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) raises OverviewIncomplete instead of silently stopping short. Either wait first (load(wait=True) / wait_until_loaded()), pass follow=True to tail items as they arrive (and break when your condition is met — handy during a live capture), or snapshot=True for 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 lifecycleconnect(), recording(), start/stop/abort.
  • Overview navigation — scoped, bounded-by-construction cursors over the tree and over search, batch-by-default pages, and handle-free ItemRecord snapshots.
  • Markers — typed MarkerColor, add at a time / on the selected (or any) overview item, and read all markers back as handle-free Markers.
  • Exports — generic export() + typed wrappers for the base modes, typed option carriers (with a BluetoothPacketLossMode enum), an offline export_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 facetsanalyzer.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 raises NotAvailable if the connected analyzer isn't that product.
  • Logic signalslogic_signals_state() (level bitmask at a time) and find_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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ellisys_analysis_automation-0.1.0.tar.gz (111.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ellisys_analysis_automation-0.1.0-py3-none-any.whl (131.5 kB view details)

Uploaded Python 3

File details

Details for the file ellisys_analysis_automation-0.1.0.tar.gz.

File metadata

File hashes

Hashes for ellisys_analysis_automation-0.1.0.tar.gz
Algorithm Hash digest
SHA256 be92585acdc93a8640d8515404eeb6add24d86f88d417e0c3f653bf38a1101f6
MD5 6d370e04138e26537640f506c6c4f43c
BLAKE2b-256 a59b55ec53d54fdf7758e883611bc4f04340bac514195b553fddab3d3138a649

See more details on using hashes here.

File details

Details for the file ellisys_analysis_automation-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for ellisys_analysis_automation-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 28625e4ecaa5e565a67856ce3e118609197b6294b57670f621a99fc5cf209ace
MD5 b523143ca58752f0863e9506985b8a19
BLAKE2b-256 6efd7f6efd27dfd7ab8312dbb351dd25c31eb38af864e9c23194e5c653fdc05f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page