michaelsthr/pyvse

GitHub: michaelsthr/pyvse

Stars: 1 | Forks: 0

# pyvse Python SDK for IFM VSE100 / VSA004 acceleration sensors. Reverse-engineered communication protocol. Not affiliated with or endorsed by IFM. ## Install pip install pyvse **Dependencies:** `numpy` (required), `pandas` + `matplotlib` (optional, for export/visualization). ## Quick start ### One-shot collect import pyvse with pyvse.connect("192.168.0.1") as client: data = client.raw("50K").collect(seconds=5.0) data.to_csv("run1.csv") df = data.to_dataframe() # pandas DataFrame: time_s, accel_g arr = data.to_numpy() # np.ndarray shape (N,), unit: g ### Live stream import pyvse with pyvse.connect("192.168.0.1") as client: for frame in client.raw("50K").stream(batch_size=700): print(frame.g_values.mean()) # np.ndarray shape (700,), unit: g ### Stream to CSV (memory-efficient) import pyvse with pyvse.connect("192.168.0.1") as client: with pyvse.CSVSink("run1.csv", sample_rate=50_000) as sink: for frame in client.raw("50K").stream(): sink.push(frame.g_values) ### Stream to PlotJuggler import pyvse with pyvse.connect("192.168.0.1") as client: with pyvse.PlotJugglerSink() as pj: # default: 127.0.0.1:9870 UDP for frame in client.raw("50K").stream(): pj.push_all(frame.g_values) # one UDP message per sample ## API reference ### `pyvse.connect(host, port=3321, timeout=5.0) → VSEClient` Returns a context manager. Use `with` to ensure clean disconnect. ### `VSEClient` | Method | Returns | Description | |--------|---------|-------------| | `raw(rate="50K")` | `RawCommand` | rate: `"50K"` or `"100K"` | ### `RawCommand` | Method | Returns | Description | |--------|---------|-------------| | `collect(seconds)` | `RawData` | Collect fixed-length capture | | `stream(batch_size=700)` | `Iterator[RawFrame]` | Live stream; runs until interrupted | ### `RawData` | Attribute / Method | Description | |--------------------|-------------| | `g_values` | `np.ndarray` shape `(N,)`, float64, unit: g | | `sample_rate` | `int`, Hz | | `time_axis` | `np.ndarray` of timestamps in seconds | | `to_numpy()` | Returns `g_values` | | `to_dataframe()` | pandas DataFrame with columns `time_s`, `accel_g` | | `to_csv(path)` | Write CSV with `time_s`, `accel_g` columns | ### `RawFrame` | Attribute | Description | |-----------|-------------| | `g_values` | `np.ndarray` shape `(batch_size,)`, float64, unit: g | | `sample_rate` | `int`, Hz | ### `CSVSink(path, sample_rate)` Stream-friendly CSV writer. Use as context manager, call `.push(g_values)` per frame. ### `PlotJugglerSink(host="127.0.0.1", port=9870)` Pushes data to PlotJuggler via UDP JSON streamer. | Method | Description | |--------|-------------| | `push(g_values, channel="accel_g")` | Send batch mean as single message | | `push_all(g_values, channel="accel_g")` | Send each sample as individual message | ### Exceptions | Exception | Raised when | |-----------|-------------| | `VSEConnectionError` | TCP connect fails | | `VSETimeoutError` | Socket read times out | | `VSEProtocolError` | Unexpected response from device | | `VSEError` | Base class for all pyvse errors | ## Disclaimer Independent implementation developed through observation of device communication. Not affiliated with or endorsed by IFM.