Repository navigation
Releases: OpenCyphal-Garage/cynitor
Release list
v1.5.0
v1.4.0
Cynitor 1.4.0
Upgrade from 1.3.0:
- Bound to the network without a token, the server no longer starts. With
--bind 0.0.0.0(or any address that is not loopback), setCYNITOR_AUTH_TOKEN. To run open on purpose, add--insecure-no-auth. The packaged default binds to 127.0.0.1 and is not affected. - The API opens only the CAN adapters Cynitor knows, and slcan only on a serial port. To open any other python-can interface by name, start the server with
--allow-any-interface. - Pages from other sites can no longer use the API. Of this machine's own pages, only the development server on port 5500 can; add others with
CYNITOR_DEV_ORIGINS. - HTTP requests are no longer logged. Add
--access-logto log them. - The .deb service runs as its own unprivileged user in a sandbox, not as root. Its data stays in
/var/lib/cynitor. slcan adapters need no change: the service is in thedialoutgroup.
New
- Listen only (in the connect form, or
--listen-only). Cynitor sends nothing on the bus: no node-ID, no heartbeat, no requests. You see the traffic, but no node names or registers. --reconnect: a server started with--canreattaches its bus by itself after the bus goes away. Without it,/api/healthnow answers 503 while that bus is down.- Update check. The version under the sidebar links to a newer release when there is one.
--no-update-checkturns it off. - On the bus Cynitor is
org.opencyphal.cynitor, with its own version. Before, it was named after pycyphal's example app. - Each release file is signed as built by this repository's release workflow. Check a download with
gh attestation verify <file> --repo OpenCyphal-Garage/cynitor. Each file also has a.sha256, the third-party licences it bundles, and the list of package versions inside.
Fixed
- Frames lost on a busy bus are counted. Past what Cynitor can decode, frames the kernel drops are counted as dropped and warned of. Before, the dashboard said none were lost. A node flooding the bus is also no longer reported offline because its heartbeats were among the drops.
- Register writes:
- A number is sent in the register's own type, and a value the node does not take answers 409, saying what the register holds. Before, a number of another type went out unconverted and the API said ok.
- Writing a register the node does not have says so. Before, it called it a type mismatch.
- Register writes and firmware updates now appear in the node's History.
- A node that answers the register list only partly fails in seconds, with the reason.
- Service calls wait the full 5 s. A node that does not answer gives 504, and one that went offline 409.
- The live view follows a reconnect. A dashboard left open across a disconnect and connect kept showing nothing.
- Times are shown in your own timezone. Before, a browser in another timezone than the server read "last seen" hours o
- A node's card shows its own messages only. On a subject several nodes publish, it showed another node's until its ow
- A full disk:
- A database that cannot be written is shown in the dashboard and its losses counted. Before, it logged 55 tracebacks a
- A raw log stops alone, without ending the session.
- A raw log now stops at 4 GiB, or with 512 MiB left on the disk.
- Bus load on CAN FD reads "unknown" where it cannot be measured. Before, a busy CAN FD bus read 0 %.
- Port lists and registers: service masks show the IDs they set, bit registers read true and false, diagnostics show their severity name, and confirmations name the device.
- Demo devices and test nodes no longer leave an offline device behind after each connect or deletion.
- Anonymous heartbeats are ignored. Before, each one logged an error with a traceback.
- Security:
- The auth token is masked in the log and compared in constant time.
- The dashboard cannot be framed by another site.
- Responses no longer name the server's versions or file paths.
- Streams, texts and uploads are capped.
- Running it: a server that cannot start exits with status 1. One started from a shell outlives that shell. The .deb tce and stops it on removal.
Download
- Debian, Ubuntu:
cynitor-server_1.4.0_amd64.deb(sudo dpkg -iit, then runcynitor-server) - Other Linux:
cynitor-server-1.4.0-x86_64.AppImage, or the bare binarycynitor-server-1.4.0-linux-x86_64 - Windows:
cynitor-server-1.4.0-windows-x86_64.exe
v1.3.0
Cynitor 1.3.0
Upgrade from 1.2.0: the allocator no longer starts by itself
In 1.2.0, Cynitor started a plug-and-play node-ID allocator on node-ID 1 whenever it connected and heard no node 1. On a bus that already had an allocator, that made a second one. And when a real node 1 came up later, Cynitor kept node-ID 1 and the two collided.
- The allocator is now off unless you ask for it: tick the Node-ID allocator box in the connect form, or use
--allocator. - It answers from Cynitor's own node-ID, so Cynitor uses one node-ID only.
- It never hands out a node-ID already heard on the bus. Once another allocator answers a request, Cynitor's stops answering, and the sidebar names the other allocator.
New
- Decode on demand (in the Server section, or
--decode-on-demand). This is for a bus that carries more than can be decoded. Cynitor decodes only the subjects you are looking at or recording. The others still show their rates, counted from their CAN frames. - Server CPU use shows in the sidebar.
Fixed
- Cynitor's own node-ID. It now picks its node-ID again on every bus, preferring 127 and then 126, which allocators never hand out. If another node uses the same ID, Cynitor says so. Before, it kept the first bus's node-ID for good and could share it with another node unnoticed.
- Unplugged USB adapter (Linux). Unplugging it now ends the session, and you can connect again. Before, it left the session "running", with no way to disconnect or reconnect short of restarting the server.
- NaN and infinity values show as "-". Before, a subject sending them looked silent.
- Registers of a node that does not answer. Reading them now fails in seconds, with the reason. Before, it took 8.5 minutes, and the page blamed the backend.
- History on a busy bus. It is written in batches, so node data and recorded service calls are no longer lost to "database is locked".
- An overloaded server no longer floods its log, and the live view no longer falls further and further behind.
- CAN FD with gs_usb adapters (CANable/candleLight) on Windows and macOS:
- Bit-rate-switched frames sample where Linux does. Before, nodes sampling at 87.5 % saw them as errors.
- CANnectivity adapters now send frames.
- Unstructured registers can be written.
- DSDL compiles with a virtual environment's Python run without activating it.
v1.2.0
Cynitor 1.2.0
New
- Simulated bus. Pick
sim:classicorsim:fdin the CAN list (or--can sim:classic) to try Cynitor with no hardware, on any OS. A demo sensor runs on it. - Test nodes. A new tab makes Cyphal nodes of your own on the bus: a name, health, mode, and up to eight publishers of any compiled type, your own DSDL included. Each number is a constant or a waveform. A free node-ID is picked for you unless you set one.
- CAN FD on Windows and macOS with CANable adapters (candleLight and slcan).
Log panel
- Shut, its toggle counts the warnings and errors that arrive.
- Times to the millisecond, repeats folded into a count, a "new below" count when you scroll up, and Save to a file.
- The server's log no longer fills with HTTP request lines.
- An empty log says why: no backend, no bus, or filters.
Changed
- Nodes and Graph: "displaced" is gone. Such devices count as offline, and the Nodes tab has Hide offline.
/api/logstakessince, and no longer returns HTTP access lines.
Fixed
- Replayed messages are listed in order, tagged
replay. - The log panel can be reached in narrow windows, and keeps your place while you read back.
- Dark theme text contrast, and about twenty smaller fixes.
v1.0.0
Cynitor 1.0.0
The first stable release.
Download
- Linux:
cynitor-server-1.0.0-linux-x86_64 - Windows:
cynitor-server-1.0.0-windows-x86_64.exe(includes what candleLight / CANable
adapters need; PEAK, Kvaser, Vector and IXXAT need their vendor's driver)
Run it and open the address it prints. The dashboard works without internet access.
Highlights
Debug tab: the transport below the DSDL
- The bus's health first: controller state, error counters, bus load, frame rates;
the details are folded below. - A frame monitor that only listens and changes nothing Cynitor sends. It shows each
Cyphal frame's priority, transfer-ID and tail bits, us frame. - Filter frames with
node:,port:,dir:and simim out. - A By ID view: a row per CAN ID with its count, cycle time and last data.
- Error frames show in red, saying what went wrong.
- Every frame kept can be scrolled to, even on a full
save a raw log from the Record tab.
Bus errors are shown, not spammed
- A bus without its 120 Ω terminator, or with a node amber
notice under the CAN status ("Bus errors · ERROR-PASSIVE – check 120 Ω termination and
bitrate"), and the CAN dot turns amber. - The server logs one line when errors start and one w
several lines per error frame.
Recording
- Recordings take every service call on the bus, Cynitor's own among them.
- Save the last minutes keeps what the bus sent be
- Search recordings by name, notes or selection. A recording needs no name: it takes
the time it starts. - Cards show their main actions, say which limit stoppa
recording waits for CAN.
DSDL
- A type that does not compile says why, with the line marked in the source.
- New type, New version (a copy at the next fr
empty custom namespaces. - A type's pane gives its description, field comments,t
is a union or deprecated. - Search by compiled name or by constant; your own types are listed first.
Compare
- Synced graphs pause, zoom, pan and take a time windo.
- A graph collapses to just its plot. Collapse All andr.
- The legend gives each series' last, min and max in view. Series are picked from
one list, found by typing. - A Nodes or Subjects plot opens its series in Compare.
- Dense lines redraw in half the time.
Graph, Nodes and Subjects
- Graph: layered layout, search-to-zoom, SVG export, k
service calls drawn, recent restarts and node-ID con - Cyphal v1.1 traffic, which Cynitor does not decode, n.
- Tables: status strips that count what needs a look,
navigation, a VSSC column, and Subjects' age and bytes per second.
Changed behaviour
- A CAN controller in ERROR-PASSIVE no longer ends the session, because it still
sends and receives. It is shown as bus errors instead. BUS-OFF still ends the session. - The controller state of a CAN FD SocketCAN interwent
unread, in the Debug tab and in the health check. - A SocketCAN interface switched between CAN FD and Cls
the session, saying so. - Bus load reads
null(unknown) instead of 0 % where - A failed DSDL compile answers
{"error": …}like every other route.
API additions
/api/status:bus_errors(state, TX/RX error coun1,dropped`.- Telemetry events:
subject_rate, the subject's total rate over its publishers. - Frame capture over the WebSocket (
capture/can_frame) and a REST snapshot of
captured frames;/api/can/transportfor the Debug GET /api/nodes/events, the recent lifecycle events of every node.PATCH /api/recordings/{id}with limits; replay see- DSDL: compile
problems with line numbers, sizes anespaces.
Fixes
About 120, among them:
- A message holding an array of structs, such as
port.List's subject-IDs, disconnected
every dashboard and lost a batch of history. It no longer does. - A port register left unset (65535) is an inactive po
- A backend that stops answering is reconnected once ieanwhile.
- Recordings stay listed, exportable and playable withreplay
moves playback there. - Fill Rate no longer freezes a plot once a field's hi
- The IBM Plex fonts are bundled instead of loaded fro
- Many keyboard and screen-reader fixes across the sidebar, the tables, and the Record,
DSDL and Compare tabs.
v0.10.0
Cynitor 0.10.0
New
Raw CAN log playback
- Play a saved candump log back as if it were the live bus (Record view → Play, at 1×, 10×, 100× or as fast as possible), with CAN disconnected.
- When a log stops, the subject types, node names and bitrates the session knew are saved beside it (
<log>.types.json), so register-typed subjects still decode on playback.
Firmware update over Cyphal
- Nodes that serve
ExecuteCommandget Update firmware… in their Services tab: pick a.bin, and Cynitor serves it to the node's Cyphal bootloader (e.g. Zubax Kocherga). - A progress bar shows the bytes read and the node's mode, and the new version shows as soon as the node restarts.
- Only
uavcan.file.Readis served, from one folder: other nodes cannot write or delete files on the host.
Types for subjects no register names
- Such subjects now say "type unknown" instead of waiting for data forever.
- Click one in Subjects: Cynitor listens for 3 s and lists the compiled types its messages fit exactly (CAN FD frame padding allowed), custom DSDL first, each with the latest message decoded as it.
- Pick one, or type any compiled type. The choice is saved and applied on every connect; a publisher's registers still take precedence.
Demo nodes
tools/demo_nodes.pyruns a demo node on a vcan to try everything above without hardware (see the README, "No hardware?").
Fixes
- Dashboard stall behind the CAN hub: with any non-SocketCAN adapter, the event loop could freeze for seconds to minutes whenever a subscription was created or closed, waiting on a python-can lock. This was also the cause of the flaky Ubuntu integration job.
- Own node-ID on SocketCAN without yakut.
- Unanswered GetInfo: when a node sends heartbeats but does not answer, the log now says why (e.g. a Classic CAN node on a CAN FD bus).
- Numeric arrays (e.g.
float32[3]) were shown as garbage text; they are numbers now. - Small UI fixes: no allocator warning at startup, the plotted
timestampseries starts hidden, and the Cyphal logo is visible in dark mode.
API changes
All additive; nothing existing changed. Details in WEBSOCKET_README.md.
| Endpoint | Purpose |
|---|---|
POST /api/rawlogs/{name}/play |
Play a raw log as the bus |
GET/POST /api/firmware, DELETE /api/firmware/{name} |
List, upload, delete firmware files |
POST /api/nodes/{id}/firmware |
Start a node's firmware update |
PUT/DELETE /api/subjects/{id}/type |
Set or clear a subject's type |
GET /api/subjects/{id}/type-guesses |
Guess a subject's type from its payloads |
GET /api/nodes |
Adds subject_types (type and who set it) |
Data folder
New entries, created only when used:
raw/*.types.json: playback sidecarsfirmware/: uploaded firmware filessubject_types.json: the subject types you set
Testing
- Backend unit tests: 697 pass on Python 3.10 and 3.12.
- Frontend e2e: 15/15 pass.
- Integration (Classic and CAN FD, through the hub) now also covers playback, a full firmware transfer, and guessing and setting a subject's type.
- Checked live on a CAN FD vcan against the demo nodes.
v0.9.0
Cynitor 0.9.0
New
- Cyphal/CAN FD. On SocketCAN, Cynitor follows the interface: set it up for CAN FD (
ip link set can0 type can bitrate … dbitrate … fd on, ormtu 72on a vcan) and it is used. PEAK, Kvaser, Vector and IXXAT adapters run CAN FD with--data-bitrateor the new selector under the bitrate in the dashboard. Every node on a CAN FD bus must run CAN FD. - Raw CAN logs. Record every frame on the bus to a candump
.logfile from the Record view and download it. python-can, SavvyCAN and can-utils read it;log2ascconverts it to Vector ASC. - Node commands. Nodes that serve
uavcan.node.ExecuteCommandget Restart and Factory reset buttons. - Diagnostics.
uavcan.diagnostic.Recordmessages now appear in the log panel for every node. - Conflicts flagged. Two nodes sharing a node-ID, or publishing one subject with different types, show up in the node's History.
Security
- The API and live stream refuse requests from other websites' pages, which could previously command nodes through your browser. Tools like curl and scripts are unaffected.
- The dashboard works without internet access: its libraries are bundled.
Fixes
- A lost register-list reply no longer leaves a node's subjects undecoded for good.
- Message rates are per node (a node's Heartbeat no longer shows the whole bus's rate).
- Timestamps come from the CAN driver.
- Dropped messages are counted and shown next to the CAN rate. History and recordings write about 20× faster.
- Composite service request fields are all sent. Service responses are JSON.
- Clicks on Record view buttons (Stop, Export, …) are no longer lost while a recording runs. Double-click to add in the Record pickers works again.
- Recording exports work when an access token is set.
- The sidebar shows the real version (it said v0.3.2).
- Clearer offline nodes in the table ("last seen …"), a Dark mode switch, and a larger detail panel.
Behaviour changes
- Bus load for non-SocketCAN adapters is counted as
canbusloadcounts it, so it reads about 20% higher than before. - Restarts appear in node History one heartbeat later.
- Service call
responseis JSON text. - Browser pages served from other origins can no longer call the API; serve the dashboard from Cynitor or from localhost.
v0.8.0
v0.7.2
Cynitor v0.7.2
The port is now configurable
./cynitor-server --bind 0.0.0.0 --port 9099Fixes addresses the server advertises
Both now follow reality. The WebSocket URL is derived from the request, so it
is also correct behind a reverse proxy or when reached by hostname rather than
localhost — which was wrong before regardless of the port.
v0.7.1
Cynitor v0.7.1
Passing an interface that does not exist used to exit with a Python
traceback, taking the dashboard down with it. Also if there are
no CAN interfaces at all, it prints the commands to create a
virtual one instead.
The auth token is shown at startup
Generating a token with $(openssl rand -hex 24) is now printed once:
Auth token (paste this into the dashboard when prompted):
a3f9c2e1b8d470563a...It is written straight to the terminal rather than logged, so it stays out of
/api/logs, the dashboard's log panel, and the system journal. Runs without
a terminal, which is every supervised run, print nothing.
The startup banner no longer contradicts itself
A direct-mode start printed both Mode: direct (attached to ... at startup)
and Selection-mode startup (no --can) four lines apart. The condition was
inverted.