3. PsyProbe Configuration
Configuring the built-in web interface: ports and web roots, custom subsites, custom tabs, private data, RequestStore catalogs and custom visualisers.
PsyProbe architecture
PsyProbe is Psyclone's built-in HTTP interface: point any browser at the main port (http://localhost:10000/ by default) and you get a live, self-updating view of every node, space and component. It serves static HTML/JS from a web root, and answers a small set of dynamic API endpoints backed by the running system.
The <psyprobe> element
<psyprobe location="otherdir/html" port="8080" defaultport="no">
<alias name="robot" location="/somedir/html" default="index.html" />
<post name="TestMove" type="Robot.Command.Move.Forward" />
</psyprobe>
| Attribute / child | Meaning | Default |
|---|---|---|
location | Web root directory for PsyProbe (overrides the auto-detected html dir and the html= cmdline) | built-in autodetect |
port | Adds a dedicated PsyProbe HTTP interface on this port | shares main port |
defaultport | no removes PsyProbe from the main port | on main port |
<alias> | Custom subsite: URL prefix → any local directory, optional default file | — |
<post> | A clickable manual-test post in the PsyProbe UI (same attributes as a module-level post, including XML content) | — |
<alias> children the loop reuses the wrong index, so in practice only the first alias is reliably read. Prefer a single alias pointing at a directory tree.Custom subsites
<alias name="robot" location="/somedir/html" default="index.html" /> maps http://host:port/robot/anydir/anyfile to /somedir/html/anydir/anyfile — any local path can be published under the PsyProbe port. This is the simplest way to ship a complete custom operator UI (the CoCoMaps robots served their whole control panel this way). Alternatively, just drop files into the web-root tree and load http://localhost:10000/mycustompage.html.
Creating custom tabs
Every component page in PsyProbe has standard tabs (Performance, Activity, Subscriptions, Log, Data). A component can add its own tab by pointing at an HTML element template in the web root:
api->addPsyProbeCustomView("Stored Messages", "elements/whiteboardmessages.html");api.addPsyProbeCustomView("Stored Messages", "elements/whiteboardmessages.html")A template is a plain HTML fragment with a script implementing two functions; PsyProbe instantiates it per component:
<script>
var TemplateCompID; // set by PsyProbe
var TemplateCompName;
function loadTemplate($target, compID) {
// called once; componentMap[compID] holds the component record
}
function updateTemplate($target, compID) {
// called every update cycle; refresh the view
}
</script>
The bundled elements/ directory of the web root is the reference library: elements/whiteboardmessages.html (the Whiteboard's own Stored Messages tab) is the canonical example to copy, and the other elements/*.html templates show the same pattern for performance panes, dataflow views and hierarchical diagrams. Custom tabs can also be declared in the spec with a <customview name=".." template=".."> child on the component.
Working with private data
Any component can publish binary or textual blobs as private data; give it a mimetype and it appears in the component's Data tab and becomes fetchable over HTTP:
// component side
api->setPrivateData("My Data", str.c_str(), str.length(), "application/json");
// browser / AJAX side
GET /api/getcomponentdata?compid=15&name=My%20Data&format=json# component side
api.setPrivateData("My Data", str, "application/json")
# browser / AJAX side
GET /api/getcomponentdata?compid=15&name=My%20Data&format=jsonSupported formats on the GET are text, xml, json, html and binary (e.g. image/bmp data renders as an image). You need the component ID, the entry name and the stored format. This is extension path number two: a custom page polling getcomponentdata can visualise anything a module chooses to expose.
RequestStore: serving live messages over HTTP
The RequestStore catalog subscribes to messages system-wide, keeps the most recent, and serves parts or whole messages via the web API — the standard way to feed custom dashboards without writing any C++ on the web side:
<catalog name="RequestStore" type="RequestStore">
<trigger name="VideoFrame" type="robot.sensor.video" />
<trigger name="Status" type="Robot.Status" />
<setup>
<store name="VideoFrame" trigger="VideoFrame" datatype="raw" mimetype="image/bmp" />
<store name="Status" trigger="Status" mimetype="application/json" maxkeep="1" />
<store name="StatusTime" trigger="Status" key="timetext" mimetype="text" />
</setup>
</catalog>
GET /api/query?from=RequestStore&query=VideoFrame
GET /api/query?from=RequestStore&query=Status
| Store attribute | Meaning |
|---|---|
name | Request name used in the query URL (required) |
trigger | Source trigger feeding this store (required) |
key | A user entry, or header fields time (µs since year 0), timetext, type, size, content; omitted ⇒ whole message rendered as JSON/XML/HTML/TEXT per mimetype |
keytype | Reserved; not currently used Stub |
datatype | raw = raw pixels; the message must contain width/height and a valid bitmap is built |
mimetype | Required; standard (application/json, text/html, text/xml) or short forms json/xml/text |
maxkeep | History count (default 1) |
maxfrequency | Max messages kept per second (rate limit) |
Custom visualisers: putting it together
The four extension paths, in increasing effort:
- Custom subsite / plain page — static HTML in the web root or an alias; fetches data with AJAX.
- RequestStore — declare stores in the spec; the page polls
/api/query. No native code. - Private data — the module computes exactly what to show (JSON, bitmap…) and publishes it; the page polls
/api/getcomponentdata. - Custom tab — an element template registered via
addPsyProbeCustomViewor<customview>; integrates into PsyProbe's own component pages and update cycle.