# Psyclone Web Interface API Specification

This document describes the web API and static resources for the **Psyclone web interface**, implemented by **PsyProbe** (entry point: `PsyProbe.cpp`). It is intended to support modernising the Psyclone web UI (e.g. building a new front-end that reuses the same backend).

---

## Overview

- **Server:** Built-in HTTP server (PsyProbe) bound to a configurable port (e.g. from Psyclone config).
- **Static root:** Files are served from the **html** subdirectory (or a path set via `setRootDir`). Aliases can map URL subpaths to other directories.
- **Request routing:** The path part of the URL (without query string) is matched against:
  1. **API:** Paths starting with `api/` → dispatched to the corresponding API handler (e.g. `api/getmessage` → `API_GetMessage`).
  2. **Named pages:** Exact match against registered page names (e.g. `loadelement`, `shutdown`) → page handler.
  3. **Static files:** Otherwise the path is resolved under the root directory (or an alias). `.html` and `.txt` are read as text; other files are served with MIME type by extension.

---

## Static Files and Templates

| Template name   | File                    | Purpose |
|-----------------|-------------------------|---------|
| MainPage        | main.html               | Main dashboard |
| SimplePage      | simplepage_template.html| Simple hierarchy page |
| LoadElement     | loadelement.html        | Element viewer frame (placeholders: TemplateURLPlaceholder, TemplateCompNamePlaceholder, TemplateCompTypePlaceholder) |

**Key front-end assets** (loaded by main.html and element views):

- **Scripts:** jquery/jquery.min.js, psyutils.js, system.js, main.js, visjs/vis.js
- **Styles:** main.css, visjs/vis-network.min.css
- **Elements:** html/elements/*.html (e.g. systemlog.html, componentprivatedata.html, controlpanel.html, whiteboardmessages.html, timeseriescatalog.html, ccmcatalog.html, hierarchicaldiagram.html)

---

## Page Routes (HTML)

| Path            | Handler       | Description |
|-----------------|---------------|-------------|
| `/` or `index.html` | MainPage     | Main dashboard (main.html). Requires network ready. |
| `simplepage`    | SimplePage    | Simple page with node/space/component hierarchy. |
| `shutdown`      | ShutdownPage  | Initiates Psyclone shutdown (3s). Returns HTML confirmation. |
| `subs`          | SubscriptionPage | Subscriptions page. |
| `ids`           | IDPage        | ID page. |
| `loadelement`   | LoadElement   | Loads loadelement.html and replaces placeholders. **Required query:** `url=...`. Optional: `nodeid`, `compid`, `node`, `comp` (for display name/type). |

---

## XML Feeds

| Path                    | Handler              | Description |
|-------------------------|----------------------|-------------|
| `xml` or `main.xml`     | XMLMain              | Main system XML (`getMainXML()`). |
| `system.xml` or `time.xml` | XMLSystem        | System/time XML (`getSystemXML()`). Used by UI for clock and connection check. |
| `performancematrix.xml` | XMLPerformanceMatrix | Performance matrix XML. |

All return **text/xml**. On error: `<error code="-1" text="Couldn't generate XML" />`.

---

## API Endpoints (prefix: `/api/`)

All API routes use the path prefix **api/** (e.g. `GET /api/getmessage`). Errors typically return **text/xml** or **application/json** with `errorcode` / `code` **-1**.

### triggeractivate

**GET** `/api/triggeractivate`

Deliver a trigger message to a component trigger by name.

| Parameter | Required | Type   | Description |
|-----------|----------|--------|-------------|
| compid    | Yes      | uint32 | Component ID |
| name      | Yes      | string | Trigger name |

**Success:** `text/xml`: `<error code="0" text="Operation success, one trigger delivered" />`  
**Errors:** Invalid parameters; Couldn't find trigger; Couldn't deliver trigger message.

---

### postactivate

**GET** `/api/postactivate`

Activate all posts for a component by name; sends one message per post spec.

| Parameter | Required | Type   |
|-----------|----------|--------|
| compid    | Yes      | uint32 |
| name      | Yes      | string |

**Success:** `text/xml`: `<error code="0" text="Operation success, N posts processed" />`  
**Errors:** Invalid parameters; Couldn't find post; Couldn't process post messages.

---

### getcomponentkeys

**GET** `/api/getcomponentkeys`

Returns the keys and value types of component private data.

| Parameter | Required | Type   | Description |
|-----------|----------|--------|-------------|
| compid    | Yes      | uint32 | Component ID |
| format    | No       | string | `json` (default) or `xml` |

**Response:** **application/json** (object key → type) or **text/xml** (TextJoinXML with tags "key", "data").

---

### getcomponentdata

**GET** `/api/getcomponentdata`

Returns raw component private data by key name.

| Parameter | Required | Type   | Description |
|-----------|----------|--------|-------------|
| compid    | Yes      | uint32 | Component ID |
| name      | Yes      | string | Data key name |
| format    | No       | string | Override/hint: `xml`, `json`, `html`, `binary`, `text` |

**Response:** Content-Type from stored mimetype or format; body is raw data.

---

### getmessage

**GET** `/api/getmessage`

Returns a message by memory ID (copy from temporal store).

| Parameter | Required | Type   | Description |
|-----------|----------|--------|-------------|
| memid     | Yes      | uint64 | Message memory ID |
| format    | No       | string | `xml`, `json`, `binary`, or default (XML as text) |

**Response:** text/xml, application/json, application/octet-stream, or text/plain.

---

### retrievemessages

**GET** `/api/retrievemessages`

Retrieves messages from the temporal store by criteria.

| Parameter   | Type   | Description |
|-------------|--------|-------------|
| source      | string | Component name (resolved to ID) |
| maxage      | number | Max age in seconds (converted to ms) |
| maxcount    | uint32 | Max number of messages |
| type        | string | PsyType string |
| key         | string | Index key name (default: `time`) |
| keytype     | string | `string`, `integer`, `float`, `double`, `time` |
| tag         | uint32 | Message tag |
| from        | string | Component name (from) |
| to          | string | Component name (to) |
| starttime   | uint64 | Start time |
| endtime     | uint64 | End time |
| startint    | int64  | Start bound (integer index) |
| endint      | int64  | End bound (integer index) |
| startfloat  | float  | Start bound (float index) |
| endfloat    | float  | End bound (float index) |
| startstring | string | Start bound (string index) |
| endstring   | string | End bound (string index) |
| format      | string | `json` or `xml` (default: xml) |

**Response:**

- **XML:** `<messages count="N">...</messages>` (each child is a message XML).
- **JSON:** `{ "messages": [ ... ] }`.

---

### query

**GET** `/api/query`

Sends a **CTRL_QUERY** message to a component and returns the component’s reply. All query parameters are added to the message. The component may reply with XML, JSON, HTML, TEXT, binary, or CORS OPTIONS.

| Parameter | Required | Description |
|-----------|----------|-------------|
| from      | Yes      | Component name (resolved to ID) |
| query     | No       | Query string (often used by component) |
| list      | No       | List parameter |

**Response:** Determined by the component’s reply message:

- **ResultCode** (HTTP-like status)
- **CACHE** (e.g. "yes" for cacheable)
- One of: **XML**, **JSON**, **HTML**, **TEXT**, **BINARY** + **MIMETYPE**, or **OPTIONS** + **ORIGIN** for CORS.

Used by the UI for: control panel (OptionSelect, AddPIN, Reset, BackNavigation, html), time series catalog (list=all, query=...), CCMCatalog (query=identity, map, last, post, etc.), hierarchical diagram (getcomponentdata), and others.

---

### post

**POST** `/api/post`

Posts a message to a **named post spec**. Request body/query parameters are converted to a DataMessage; the post spec sets type, to, tag, ttl, policy and adds content.

| Parameter | Required | Description |
|-----------|----------|-------------|
| name      | Yes (query or body) | Post name (must exist in PsyProbe’s posts map) |

**Body:** Form or query params become message keys. The server also adds HTTP_OPERATION, REQUEST, URI, SOURCE, and header/param entries.

**Success:** **application/json:** `{ "errorcode": 0, "text": "Operation success, post 'name' message sent" }`  
**Error:** **application/json:** `{ "errorcode": -1, "text": "..." }`

---

### getlog

**GET** `/api/getlog`

Returns log entries (system-wide or for a component).

| Parameter | Required | Type   | Description |
|-----------|----------|--------|-------------|
| compid    | No       | uint32 | Component ID; omit for system log |
| format    | No       | string | `json` (default) or `xml` |
| maxcount  | No       | uint32 | Default 30 |
| maxlevel  | No       | uint8  | Max log level |
| maxagems  | No       | uint32 | Max age in milliseconds |

**Response:** **application/json:** `{ "log": [ LogEntry, ... ] }` or **text/xml:** `<log>...</log>`.

---

## How the Front-End Uses the API

- **main.html / main.js:** Load `main.xml`, `time.xml`, `main_template.xml`; poll `main.xml` or `time.xml` for clock and connection check.
- **system.html:** Load `system.xml`.
- **system.js:** `getMessageByMemID(memID, format)`, `getComponentPrivateData(compID, dataName, format)`, `triggerActivate(compID, name)`, `postActivate(compID, name)`.
- **elements/whiteboardmessages.html:** `GET /api/retrievemessages?source=&maxcount=&maxsize=&maxage=&format=...`
- **elements/timeseriescatalog.html:** `GET /api/query?from=&list=all`, `GET /api/query?from=&query=&sinceid=&maxcount=`
- **elements/systemlog.html:** `GET /api/getlog?maxcount=&maxlevel=&maxagems=&format=json`
- **elements/componentlog.html:** `GET /api/getlog?compid=&maxcount=&maxlevel=&maxagems=&format=json`
- **elements/componentprivatedata.html:** `GET /api/getcomponentkeys?compid=&format=json`, `GET /api/getcomponentdata?compid=&name=&_=...`
- **elements/controlpanel.html:** `GET /api/query?from=&query=OptionSelect|AddPIN|Reset|BackNavigation|html&...`
- **elements/hierarchicaldiagram.html:** `GET /api/getcomponentdata?compid=&name=&format=json`
- **elements/ccmcatalog.html:** Multiple `/api/query?from=&query=...` (identity, map, last, post, etc.)

---

## Startup Behaviour

When PsyProbe status is not **PSYPROBE_SYSTEM_READY**:

- Requests to **api/** or **\*.xml** return **HTTP 200** with **Refresh: 3** and body: `<error code="-1" text="PsyProbe starting up, please wait..." />` (XML) or plain text message.
- Other requests get an HTML “PsyProbe starting up, please wait...” with Refresh: 3.

---

## JSON Spec Location

A machine-readable API specification is available in the repo: **docs/psyclone-web-api.json**.
