Skip to main content

Headless datalogger: leave and rejoin

Start a capture that runs for hours, let the script exit, and come back later to collect the results. Nothing has to stay connected in between.

This works because the server owns the workspace. A disconnect destroys nothing: the capture keeps running, the data stays reachable, and any client can attach to it later. It is also what lets a test bench hand a session from one script to the next.

Starting and walking away​

from ikalogic_scanastudio import ScanaStudio


def start(device: str = "se254") -> int:
with ScanaStudio.connect() as server:
workspace = server.create(device)
workspace.capture.start(samples=2_000_000_000, sample_rate=25_000_000)
print(f"workspace {workspace.id} is capturing; this script can now exit")
return 0

Note what does not happen here: no wait(), and no close(). Closing the ScanaStudio client ends the connection; the workspace goes on capturing without it.

Coming back for the results​

from ikalogic_scanastudio import ScanaStudio


def rejoin() -> int:
with ScanaStudio.connect() as server:
sessions = server.workspaces()
if not sessions:
print("the server holds no workspace")
return 1

for session in sessions:
print(
f" {session.workspace_id} {session.device_name} {session.state} "
f"{session.last_sample} samples {session.clients} client(s)"
)

workspace = server.attach(sessions[0].workspace_id)
print(f"\nattached to {workspace.id}, now at {workspace.capture.last_sample}")

workspace.capture.stop()
print(f"stopped at {workspace.capture.wait()}")

workspace.save("/data/overnight.scana")
workspace.close()
return 0

Example output. The listing, then the rejoin:

192139071722857 SE254 (demo) done 1000000 samples 0 client(s)
192139071722863 SE254 (demo) sampling 1225000000 samples 0 client(s)

attached to 192139071722863, now at 1225000000
stopped at 1225000000

0 client(s) on a sampling session shows that nothing was watching it, and it kept going anyway.

attach replays the workspace's full state, so once connected you see the capture configuration, the decoders, the annotations and the log.

Notes for your own bench​

Size the capture, not the timeout. samples is what bounds the run. Do not try to make a long capture work by raising a timeout: start() and leave.

Find your workspace by a stable key. The example attaches to sessions[0]. On a server holding several, match on device_name, or on the id you printed when you started:

mine = next(s for s in server.workspaces() if s.device_name == "SP259 (sn 1004250000604)")
workspace = server.attach(mine.workspace_id)

clients tells you who else is watching. A workspace with zero clients is not at risk. A workspace with one may be open in somebody's ScanaStudio window, and closing it takes their session away too.

Stop before you read. A capture still running gives you a moving last_sample. stop() then wait() settles it.

Check whether it is still running first. wait() waits for a state change. If you attach to a workspace that is already done and call wait(), it blocks until the timeout. Check capturing or state first:

session = next(s for s in server.workspaces() if s.workspace_id == wanted)
workspace = server.attach(session.workspace_id)

if session.capturing:
workspace.capture.stop()
last = workspace.capture.wait(timeout=60)
else:
last = workspace.capture.last_sample # already finished; just read it

workspaces() is the reliable place to read this: it reports the workspace's state as the server sees it, before you attach.

Nothing cleans up after you

The server never closes a workspace on its own. A capture you start and forget will still be there tomorrow, holding memory and a device. Whatever starts a workspace should have something that eventually closes it.

This is also how you hand work between scripts

The same mechanism lets one script arm a capture, a second collect it, and a third export it. All they share is a workspace id.