AcTuiSense
A cross-platform terminal UI to configure Actisense NMEA 2000 gateways (NGT-1, NGW-1, NGX-1) over a serial port or TCP — the open, scriptable alternative to the Windows-only Actisense NMEA Reader → Hardware Configuration.
Runs anywhere Python runs: Linux, macOS, and Windows (PowerShell / Windows Terminal).
Activity Log tab — every gateway exchange (line, time, action, result, detail), fed by a live Get-Operating-Mode poll plus your own actions, just like NMEA Reader's command log:
Firmware tab — update NGX-1 / WGX-1 firmware over the reverse-engineered
BstFt protocol, no Actisense Toolkit required: read the currently-installed version,
Browse… for the .zip, and watch a live progress bar while the whole archive
streams to the gateway (which decrypts the inner .actp itself):
Validated end-to-end against a real Actisense NGT-1 and NGX-1 — reading the operating mode and Rx/Tx enable lists, toggling per-PGN filters, activating, and committing to EEPROM.
Why
The NGT-1 will only transmit a PGN onto the bus if that PGN is in its Tx PGN Enable List, and only receives the PGNs in its Rx PGN Enable List when in Filter mode. By default these lists are minimal, so injected/forwarded application PGNs are silently dropped. Actisense ships a Windows GUI to edit these lists; AcTuiSense does the same job from any terminal, plus a plain CLI for automation.
Heads-up: this writes to your gateway's configuration (and optionally its EEPROM). It is an independent project, not affiliated with Actisense. See CREDITS.md for protocol provenance.
Install
# install straight from GitHub (recommended), with the WAGO/can0 extra:
pipx install "actuisense[wago] @ git+https://github.com/phobicdotno/actuisense.git"
# core only (serial / TCP gateway config, no can0 monitor):
pipx install "git+https://github.com/phobicdotno/actuisense.git"
# from a local checkout:
pipx install ".[wago]" # or: pip install -e ".[wago]"
Use pip install --user "<same spec>" instead of pipx if you prefer.
The TUI checks GitHub once at startup for a newer release (fail-silent, works fine
offline) and shows a toast when one exists; actuisense --version prints the same
hint. Opt out with ACTUISENSE_NO_UPDATE_CHECK=1.
Requires Python ≥ 3.9, pyserial, and textual (plus paramiko for [wago]).
Use
TUI
actuisense tui # start disconnected, then pick a connection
actuisense tui -p /dev/ttyUSB0 # Linux/macOS serial
actuisense tui -p COM5 # Windows
actuisense tui -p tcp://192.168.1.50:60002 # networked gateway (e.g. W2K-1)
Arrow keys / mouse to move, space toggles the RX or TX box on the focused PGN, type in the filter box to narrow the list, then Commit → EEPROM to persist.
Connection dialog (Ctrl+O): choose the source without restarting — a serial
port (auto-detected ports are listed) + baud, a tcp:// gateway, or a WAGO PLC.
Bus Monitor — listen on a WAGO PLC's can0
A WAGO PFC200 on the same NMEA 2000 backbone exposes the bus as SocketCAN (can0).
Log in with a username/password over SSH and the Bus Monitor tab streams live
traffic straight off the wire — the ground truth for what the gateway is actually
transmitting. Pick WAGO PLC (can0) in the Connection dialog, or from the CLI:
actuisense monitor --host 10.0.0.202 -u root -P wago # decoded can0 dump
actuisense monitor --host 10.0.0.202 -u root -P wago --iface can1 -n 50
Read-only: it never writes to the bus or the gateway. Needs the wago extra
(pip install actuisense[wago], which adds paramiko).
CLI (scriptable, no UI)
actuisense info -p /dev/ttyUSB0 # hardware + operating mode + lists
actuisense enable tx 127512 127514 127751 -p /dev/ttyUSB0 --commit
actuisense disable rx 130306 -p /dev/ttyUSB0
actuisense mode rxall -p /dev/ttyUSB0 # filter | rxall | convert
actuisense mode convert -p COM5 # NMEA 0183<->2000 conversion mode
actuisense list tx -p /dev/ttyUSB0
actuisense fw NGX-1-Release-v3.068.1986.zip -p COM5 # NGX-1/WGX-1 firmware update (CRC auto-filled for known files)
actuisense baud -p COM5 # show serial baud codes; --set 5,7 to change (Convert mode only)
Firmware update (NGX-1 / WGX-1)
actuisense fw <firmware.zip> (and the Firmware tab in the TUI) push an Actisense
firmware .zip to the gateway over the reverse-engineered BstFt protocol — no
Actisense Toolkit needed. The whole .zip is streamed in 200-byte windows with
XON/XOFF flow control; the device unwraps and decrypts the inner .actp itself.
- Progress bar with percent / KB / rate / ETA, and a confirmation prompt.
- CRC: the Actisense end-of-transfer CRC-32 uses a non-standard polynomial that
isn't recovered yet, so the CRC is auto-filled by filename for files we've seen
(e.g.
NGX-1-Release-v3.068.1986.zip). For any other file, pass it explicitly with--crc 0x…(read from a Toolkit*-bstft.log); a wrong/placeholder CRC is safely rejected by the device (nothing is flashed). - The gateway must be in Convert mode at the chosen baud — set it directly with
actuisense mode convert(no NMEA Reader / power-cycle needed). - 115200 baud pre-flight: firmware updates are refused when the serial link is
not at 115200 baud (the NGX-1-USB factory rate). A gateway whose stored baud has
drifted (e.g. to 38400) half-works at other speeds and has caused very confusing
failed-update sessions — normalize it first (
actuisense baudor the Toolkit Hardware Config tab), reconnect at 115200, then flash. CLI escape hatch:--force-baud. The TUI header always shows the current mode + baud so a drifted link is visible at a glance.
⚠️ Do not remove power until the gateway's LED returns to its normal pulse. Protocol
details: docs/reverse-engineering/bstft/.
Settings coverage
| Setting | CLI | TUI | Notes |
|---|---|---|---|
| Operating mode (Filter / Receive-All / Convert) | mode |
m |
the 0x11 command (Filter=1, Receive-All=2, Convert=4) |
| Per-PGN Rx enable (all 339 PGNs) | enable/disable rx |
r |
0x46 |
| Per-PGN Tx enable (all 339 PGNs) | enable/disable tx |
t |
0x47 |
| Activate enable lists | implicit | a |
0x4B |
| Commit to EEPROM (persist) | --commit |
c |
0x01 |
| Read current Rx/Tx lists & mode | info / list |
on connect | parsed |
| Raw diagnostic queries (hw/product/total-time) | raw |
— | read-only hex; vendor-binary fields are not guessed |
| Serial (port) baud codes | baud / --set |
— | 0x12/0x16 GET+SET; codes read from device or supplied explicitly (closed rate<->code table) |
| Activity log of every exchange (+ live poll) | — | Activity Log tab | line/time/action/result/detail; p pauses polling |
| Choose connection (serial/baud, TCP, WAGO) | -p / monitor |
Ctrl+O |
serial port auto-detect; start disconnected |
| Live can0 bus monitor (via WAGO PLC SSH) | monitor |
Bus Monitor tab | read-only candump; per-PGN/source aggregation |
| Firmware update (NGX-1 / WGX-1) | fw |
Firmware tab | BstFt transfer with live progress bar; Browse for the .zip, reads the installed version, CRC auto-filled for known files; see docs/reverse-engineering/bstft/ |
Deliberately not wired up yet: NMEA 0183 P-code, and
duplicate-filtering — these can disrupt the link, and their payloads are not
publicly specified, so they are left out rather than guessed. Device model/firmware
identification (via N2K PGN 126996) is a planned addition. The protocol module
already encodes the full Actisense command set, so adding these is straightforward
once each is verified against hardware.
Status
Early but working: the protocol codec is validated against real NGT-1 captures (see the tests). See CHANGELOG.md for what's wired up.
License
MIT — see LICENSE.
Release files for actuisense 0.6.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| actuisense-0.6.2.tar.gz | 73.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| actuisense-0.6.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size:131.5 kB
Release files / actuisense-0.6.2.tar.gz
| Download URL | actuisense-0.6.2.tar.gz |
|---|---|
| Size | 73.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
aa03bf01b4834fae7bb3e8fbf9807eeb23673b2cdc1e42caf679fa28e2ff45b2
|
|
BLAKE2b-256 checksum How to use checksums |
b8e23232a8df93a8e009831b775104168e98a380ca57ac6ace8047145590b66f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 6, 2026.
Transparency logRelease files / actuisense-0.6.2-py3-none-any.whl
| Download URL | actuisense-0.6.2-py3-none-any.whl |
|---|---|
| Size | 58.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
cf7c825016f3345edfb33bd2ee64047b08f7492f89b1400cbcd6116d11694e20
|
|
BLAKE2b-256 checksum How to use checksums |
e04467f6f82b412783ff149735a0212f361d8501cd1aea53e2031a229ca0537c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 6, 2026.
Transparency log