motorcortex-python
Python bindings for the Motorcortex real-time control engine. Connect to a Motorcortex server, read and write parameters, and stream live telemetry over a single TLS-secured websocket.
Installation
pip install motorcortex-python
Requires Python ≥ 3.10. Runtime dependencies (pynng, protobuf) are installed automatically.
Quick start
Recommended — Session context manager (close is automatic, even on exceptions):
import motorcortex
with motorcortex.Session(
"wss://192.168.2.100",
certificate="mcx.cert.crt",
login="admin", password="admin",
timeout_ms=1000,
) as s:
# Read a single parameter
reply = s.req.getParameter("root/Control/dummyDouble").get()
print(reply.value)
# Write a parameter
s.req.setParameter("root/Control/dummyDouble", 3.14).get()
# Subscribe to a streamed update (every 10th cycle)
subscription = s.sub.subscribe(
["root/Control/dummyDouble"], "myGroup", frq_divider=10,
)
subscription.get()
subscription.notify(lambda result: print(result[0].value))
Explicit-objects form — the original API, still supported:
types = motorcortex.MessageTypes()
tree = motorcortex.ParameterTree()
req, sub = motorcortex.connect(
"wss://192.168.2.100", types, tree,
certificate="mcx.cert.crt",
login="admin", password="admin",
)
try:
reply = req.getParameter("root/Control/dummyDouble").get()
print(reply.value)
finally:
sub.close()
req.close()
The URL grammar accepts IPv4, hostnames, and IPv6 literals both with and without explicit ports — e.g. wss://host, wss://host:5568:5567, wss://[::1], wss://[fe80::1]:5568:5567.
Unsubscribing and closing
sub.unsubscribe(subscription)is the precise control: it removes one group from the server and stops its updates. Use it whenever your application is done with a specific group but keeps running.sub.close()ends the subscribe connection for good and best-effort-removes any groups you didn't unsubscribe (so a churnedSubscribedoesn't leave stale groups loading the server).close()is terminal — a closedSubscribecannot be reconnected; create a new one (or a newSession) instead. Callingconnect()on a closedSubscriberesolves toFalse, it never raises.
If the subscribe connection drops, the library silently redials in the
background and fires your state_update callback with
CONNECTION_LOST / CONNECTION_OK. After a reconnect, call
sub.resubscribe() to restore your groups — motorcortex.connect()'s
default reconnect handler already does this for you.
Documentation
- API reference —
docs/_index.md— flat, method-by-method reference for every public class and function. Regenerated from the docstrings viapydoc-markdown. ARCHITECTURE.md— internals tour: module layout, connection lifecycle, subscribe frame format, parameter-tree cache, threading model, error contract, type conventions.examples/README.md— runnable scripts (quickstart.py,error_handling.py) that demonstrate the canonical usage patterns.CHANGELOG.md— version history.
Repository layout
motorcortex/ Python package
test/
unit/ Offline unit tests (no server)
integration/ Live tests against the vendored test_server
server/ Vendored C++ test_server (CMake project)
docs/ pydoc-markdown + stub generation scripts
benchmark/ Throughput scripts (not part of the test suite)
sandbox/ Ad-hoc repro scripts
Testing
Unit tests run offline and require only the package itself:
pip install -e .
pip install "coverage[toml]>=7.4"
python -m unittest discover -s test/unit -t .
Integration tests spawn the vendored test_server. Build it once, then run the suite:
cmake -S test/server -B test/server/build -DCMAKE_BUILD_TYPE=Release
cmake --build test/server/build
python -m unittest discover -s test/integration -t .
Coverage (line + branch). pyproject.toml sets parallel = true, so each
coverage run writes a per-process data shard; use coverage combine to
merge them before coverage report:
coverage erase
coverage run -m unittest discover -s test/unit -t .
coverage run -m unittest discover -s test/integration -t .
coverage combine
coverage report
See test/README.md for the full testing walkthrough.
Regenerating the API reference
docs/_index.md is committed and should be refreshed
before each release so the rendered reference matches the code at
the tag. The regen is two commands — pydoc-markdown first, then
format_api.sh to wrap >>> examples as fenced Python blocks and
prepend the front matter:
pip install pydoc-markdown
cd docs
pydoc-markdown pydoc-markdown.yml > _index.md
./format_api.sh
The hook-based one-shot version was dropped — it races with the
shell redirect and silently loses output. See docs/readme.md and
the comment in docs/pydoc-markdown.yml for the full rationale.
Release process
See PIPHOWTO.md for PyPI release steps and CHANGELOG.md for version history.
License
MIT — see LICENSE.
Metadata
Release files for motorcortex-python 1.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| motorcortex_python-1.2.0.tar.gz | 71.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| motorcortex_python-1.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 149.8 kB
Release files / motorcortex_python-1.2.0.tar.gz
| Download URL | motorcortex_python-1.2.0.tar.gz |
|---|---|
| Size | 71.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
97124b2776ebc2b129f818ea032b91118a0a78ec956a2e961e0513e8b2404890
|
|
BLAKE2b-256 checksum How to use checksums |
b1eb8de9a212acb1b5f22807df11eaf2db4852aa5dc4127158957a5f47215fc8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.4
|
Release files / motorcortex_python-1.2.0-py3-none-any.whl
| Download URL | motorcortex_python-1.2.0-py3-none-any.whl |
|---|---|
| Size | 78.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
dd15c344f6b90014db0ba4eec57c1b1427194ebdfda1e3cf3b7f3391905b9d35
|
|
BLAKE2b-256 checksum How to use checksums |
a927173b62a593beb19cecac2809db26ba94b701901de27387bbf8631ba984b4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.4
|