Remote and shared instruments
The server and the client do not have to be on the same machine. Put the analyser wherever the board is (a lab bench, a climate chamber, a rack in another building) and drive it from your desk or from CI.
Several clients can talk to one server at the same time, so a script and a ScanaStudio window can watch the same capture.
Opening the server to the network​
scanastudio-server is installed with the ScanaStudio application:
/usr/bin/scanastudio-server on Linux, %LOCALAPPDATA%\Programs\ScanaStudio\
on Windows, ScanaStudio.app/Contents/MacOS/ on macOS. Installing ScanaStudio
on the lab machine is enough.
It listens on 127.0.0.1:4911 by default, which accepts only local
connections. Widen it with --listen, or with the SCANASTUDIO_LISTEN
environment variable:
# On the lab machine, with the device plugged in:
scanastudio-server --listen 0.0.0.0:4911
# Same thing, from the environment:
SCANASTUDIO_LISTEN=0.0.0.0:4911 scanastudio-server
The server logs a warning when it listens beyond loopback.
The protocol has no password, no token and no TLS. Anything that can reach that
port can start and stop captures, read every workspace's data, write files on
the server's machine through save and export_csv, and shut the server
down.
Do not expose 0.0.0.0 on an untrusted network. The safe arrangements are:
- An SSH tunnel. Leave the server on loopback and forward the port:
ssh -N -L 4911:127.0.0.1:4911 user@lab-machine, then connect tows://127.0.0.1:4911as if it were local. This is the recommended default. - A VPN, so the network is one you control.
- A firewall rule admitting only the machines that need it. Bind to a
specific interface (
--listen 10.0.0.5:4911) rather than0.0.0.0.
Connecting from another machine​
- Python
- NodeJS
- Rust
- C
import os
from ikalogic_scanastudio import ScanaStudio
URL = os.environ.get("SCANASTUDIO_URL", "ws://lab-machine.local:4911")
with ScanaStudio.connect(URL) as server:
print(server.info)
for device in server.devices():
print(" ", device)
workspace = server.create("hw:SP259-000123")
workspace.capture.run(samples=1_000_000, sample_rate=25_000_000)
# This path is on the LAB machine, not on yours.
workspace.save("/data/run.scana")
workspace.close()
import { ScanaStudio } from '@ikalogic/scanastudio';
const url = process.env.SCANASTUDIO_URL ?? 'ws://lab-machine.local:4911';
const server = await ScanaStudio.connect(url);
try {
console.log(server.info);
// What is this server already doing?
for (const device of await server.devices()) console.log(' ', device.key);
const workspace = await server.create('hw:SP259-000123');
await workspace.capture.run({ samples: 1_000_000, sample_rate: 25_000_000 });
// This path is on the LAB machine, not on yours.
await workspace.save('/data/run.scana');
workspace.close();
} finally {
server.close();
}
use scanastudio_client::{ScanaStudio, Result};
#[tokio::main]
async fn main() -> Result<()> {
// Make the URL configuration, not a constant: the same program then runs
// against a local demo device and against the lab machine in CI.
let url = std::env::var("SCANASTUDIO_URL")
.unwrap_or_else(|_| "ws://lab-machine.local:4911".to_string());
let server = ScanaStudio::connect(&url).await?;
for device in server.devices().await? {
println!(" {}", device.key);
}
let workspace = server.create("hw:SP259-000123").await?;
workspace.capture()
.run(&scanastudio_client::CaptureRequest::new(1_000_000, 25_000_000),
std::time::Duration::from_secs(300))
.await?;
// This path is on the LAB machine, not on yours.
workspace
.save("/data/run.scana", std::time::Duration::from_secs(600))
.await?;
workspace.close()?;
Ok(())
}
/* ss_server_connect takes the URL; NULL means ws://127.0.0.1:4911 */
ss_server *server = ss_server_connect("ws://lab-machine.local:4911");
if (!server) {
fprintf(stderr, "connect: %s\n", ss_last_error());
return 1;
}
ss_workspace *workspace = ss_server_create(server, "hw:SP259-000123");
ss_capture_run(workspace, "{\"samples\": 1000000, \"sample_rate\": 25000000}", 300.0);
/* Written on the LAB machine. */
ss_workspace_save(workspace, "/data/run.scana", 600.0);
save(), export_csv() and open() are resolved by the server, with the
server's permissions. Against a remote server, a path you type locally means a
directory on the far end. If you need the file on your machine, fetch it
afterwards. The SDK does not transfer it for you.
Sharing one instrument​
Several clients may attach to the same server, and to the same workspace. Two useful arrangements:
A script and a human. Your script opens a workspace and captures; someone opens ScanaStudio pointed at the same server, attaches to that workspace, and watches the waveform live. Both see the same data because there is only one copy of it, on the server.
Two scripts, one after the other. One arms a long capture and exits; another attaches later to collect it. See Headless datalogger.
- Python
- NodeJS
- Rust
- C
# What is this server already doing?
for session in server.workspaces():
print(f" {session.workspace_id} {session.device_name} {session.state} "
f"{session.clients} client(s) capturing={session.capturing}")
// What is this server already doing?
for (const session of await server.workspaces()) {
console.log(` ${session.workspace_id} ${session.device_name} ${session.state} `
+ `${session.clients} client(s) capturing=${session.capturing}`);
}
// What is this server already doing?
for session in server.workspaces().await? {
println!(" {} {} {} {} client(s)",
session.workspace_id, session.device_name, session.state, session.clients);
}
char *sessions = ss_server_workspaces(server); /* JSON array */
printf("%s\n", sessions);
ss_string_free(sessions);
Example output. What a shared lab server is already doing:
192139071722857 SP259 (sn 1004250000604) sampling 412000000 samples 1 client(s) capturing=true
192139071722863 SE254 (demo) done 1000000 samples 0 client(s) capturing=false
The first session has a client attached (possibly somebody's ScanaStudio window), so closing it would take their session away too.
Notes for your own bench​
Make the URL configuration, not a constant. An environment variable lets the same script run against a local demo device while you write it and against the lab machine in CI.
Check clients before you close. A workspace with clients attached may be
open in somebody's ScanaStudio window, and close() takes their session away
too. Close your own connection instead.
A device belongs to one workspace. Two workspaces cannot capture on the same
physical device at once. On a shared server, workspaces() tells you whether the
instrument you want is already busy.
Latency affects reads, not acquisition. The capture runs on the server at full speed regardless of your link. A slow connection only slows down reading transitions and packets back. Filter on the server, and export to a file on the server rather than streaming a million packets across a WAN.
If a script needs two workspaces at once (two devices on the same lab machine, say), open two connections.