|
1 | 1 | # Process control and execution utility overview |
2 | 2 |
|
3 | 3 | `peanut` is the **p**rocess **e**xecution **a**nd co**n**trol **ut**ility for OCClib-based O² processes. Its purpose |
4 | | -is to be a debugging and development aid for non-FairMQ O² devices, where FairMQ's interactive |
5 | | -controller is not available. |
| 4 | +is to be a debugging and development aid for OCC-based and FairMQ O² devices. |
6 | 5 |
|
7 | 6 | In aliBuild it is part of the `coconut` package. |
8 | 7 |
|
9 | | -`peanut` can connect to a running OCClib-based process, query its status, drive its state machine |
| 8 | +`peanut` can connect to a running OCClib-based or FairMQ process, query its status, drive its state machine |
10 | 9 | and push runtime configuration data. |
11 | 10 |
|
12 | | -`peanut` is an interactive tool, the only information it picks up from its environment is the |
13 | | -`OCC_CONTROL_PORT` variable, which is used to connect to a running OCClib-based process. |
| 11 | +`peanut` runs in two modes depending on whether a command is passed: |
| 12 | + |
| 13 | +* **TUI mode** — interactive terminal UI (launched when no command is given) |
| 14 | +* **CLI mode** — non-interactive, scriptable (launched when a command is given) |
| 15 | + |
| 16 | +--- |
| 17 | + |
| 18 | +## TUI mode |
| 19 | + |
| 20 | +```bash |
| 21 | +peanut [flags] |
| 22 | +``` |
| 23 | + |
| 24 | +| Flag | Default | Description | |
| 25 | +|------|---------|-------------| |
| 26 | +| `-addr` | `""` | gRPC address `host:port`; if empty, falls back to `OCC_CONTROL_PORT` env var (direct mode only) | |
| 27 | +| `-mode` | `direct` | `direct`, `fmq`, or `fmq-step` (see below) | |
| 28 | + |
| 29 | +### Modes |
| 30 | + |
| 31 | +#### `direct` — OCC protobuf (default) |
| 32 | + |
| 33 | +Connects to an OCClib-based process using the standard OCC protobuf codec. |
| 34 | +The state machine operates on OCC states: `STANDBY`, `CONFIGURED`, `RUNNING`, `ERROR`. |
14 | 35 |
|
15 | 36 | ```bash |
16 | | -$ OCC_CONTROL_PORT=<some port> peanut |
| 37 | +OCC_CONTROL_PORT=47100 peanut |
| 38 | +# or |
| 39 | +peanut -addr localhost:47100 -mode direct |
17 | 40 | ``` |
18 | 41 |
|
19 | | - |
| 42 | +Control buttons: **CONFIGURE**, **RESET**, **START**, **STOP**, **RECOVER**, **EXIT** |
20 | 43 |
|
21 | | -`peanut` commands are documented inline. Each transition is applied immediately and |
22 | | -the state is updated in real time. |
| 44 | +#### `fmq` — FairMQ JSON codec with automatic multi-step sequencing |
23 | 45 |
|
24 | | -Compared to the raw gRPC API, the following limitations apply: |
| 46 | +Connects to a FairMQ device using the JSON codec. Each OCC-level button press |
| 47 | +automatically drives the full underlying FairMQ state machine sequence. |
| 48 | +The state is displayed as an OCC-mapped state (`STANDBY`, `CONFIGURED`, `RUNNING`…). |
25 | 49 |
|
26 | | -* It is not possible to perform a `GO_ERROR` transition, as this transition is only triggered from |
27 | | -user code. |
| 50 | +```bash |
| 51 | +peanut -addr localhost:47100 -mode fmq |
| 52 | +``` |
| 53 | + |
| 54 | +Control buttons: **CONFIGURE**, **RESET**, **START**, **STOP**, **RECOVER**, **EXIT** |
| 55 | + |
| 56 | +Sequences driven automatically: |
| 57 | + |
| 58 | +| Button | FairMQ steps | |
| 59 | +|--------|-------------| |
| 60 | +| CONFIGURE | INIT DEVICE → COMPLETE INIT → BIND → CONNECT → INIT TASK | |
| 61 | +| RESET | RESET TASK → RESET DEVICE | |
| 62 | +| START | RUN | |
| 63 | +| STOP | STOP | |
| 64 | +| RECOVER | RESET DEVICE (from ERROR) | |
| 65 | +| EXIT | RESET (if needed) → END | |
| 66 | + |
| 67 | +#### `fmq-step` — FairMQ JSON codec with granular per-step control |
| 68 | + |
| 69 | +Connects to a FairMQ device using the JSON codec. Exposes each individual FairMQ |
| 70 | +state machine step as a separate button. The state is displayed as the raw FairMQ state. |
| 71 | + |
| 72 | +```bash |
| 73 | +peanut -addr localhost:47100 -mode fmq-step |
| 74 | +``` |
| 75 | + |
| 76 | +| Key | Button | Transition | |
| 77 | +|-----|--------|-----------| |
| 78 | +| `1` | INIT DEVICE | IDLE → INITIALIZING DEVICE | |
| 79 | +| `2` | COMPLETE INIT | INITIALIZING DEVICE → INITIALIZED | |
| 80 | +| `3` | BIND | INITIALIZED → BOUND | |
| 81 | +| `4` | CONNECT | BOUND → DEVICE READY | |
| 82 | +| `5` | INIT TASK | DEVICE READY → READY | |
| 83 | +| `6` | RUN | READY → RUNNING | |
| 84 | +| `7` | STOP | RUNNING → READY | |
| 85 | +| `8` | RESET TASK | READY → DEVICE READY | |
| 86 | +| `9` | RESET DEVICE | → IDLE | |
| 87 | +| `0` | END | IDLE → EXITING | |
| 88 | + |
| 89 | +### Common TUI controls (all modes) |
| 90 | + |
| 91 | +| Key | Action | |
| 92 | +|-----|--------| |
| 93 | +| `n` | **Reconnect** — re-establish the gRPC connection to the controlled process. Use this when the process has been restarted after a crash or deliberate termination. | |
| 94 | +| `l` | **Load configuration** — open a file dialog to read a YAML or JSON configuration file. The path field supports tab-completion. Once loaded, the right panel shows `NOT PUSHED` until the next CONFIGURE transition, then `PUSHED`. | |
| 95 | +| `q` | **Quit** — disconnect and exit without sending any transitions. | |
| 96 | + |
| 97 | +### Connection monitoring |
| 98 | + |
| 99 | +While connected, peanut passively monitors the gRPC connection in a background goroutine and detects process termination without any button press. The strategy depends on what the controlled process supports: |
| 100 | + |
| 101 | +1. **StateStream** (OCClib processes, `direct` mode) — subscribes to the state stream; any disconnect immediately triggers `UNREACHABLE` and an error modal. State updates from the stream are also reflected in the display in real time. |
| 102 | +2. **EventStream** (FairMQ processes, `fmq`/`fmq-step` modes) — subscribes to the event stream; disconnect is detected immediately when the stream breaks. |
| 103 | +3. **Polling** (fallback) — if neither stream is available, `GetState` is polled every 2 seconds. |
| 104 | + |
| 105 | +When the process dies, the state display shows `UNREACHABLE` and an error modal appears. After restarting the controlled process, press `n` to reconnect. |
| 106 | + |
| 107 | +### Runtime configuration files |
| 108 | + |
| 109 | +Configuration files are YAML or JSON, with arbitrarily nested structure. |
| 110 | +`peanut` flattens them to dot-notation key=value pairs before pushing. |
| 111 | +Integer map keys and integer values are both handled correctly. |
| 112 | + |
| 113 | +Example (channel configuration): |
| 114 | +```yaml |
| 115 | +chans: |
| 116 | + data: |
| 117 | + numSockets: 1 |
| 118 | + 0: |
| 119 | + address: ipc://@o2ipc-example |
| 120 | + method: bind |
| 121 | + type: push |
| 122 | + transport: shmem |
| 123 | + sndBufSize: 1000 |
| 124 | + rcvBufSize: 1000 |
| 125 | + sndKernelSize: 0 |
| 126 | + rcvKernelSize: 0 |
| 127 | + rateLogging: 0 |
| 128 | +``` |
| 129 | +
|
| 130 | +This flattens to entries like `chans.data.0.address=ipc://@o2ipc-example`. |
| 131 | + |
| 132 | +--- |
| 133 | + |
| 134 | +## CLI mode |
| 135 | + |
| 136 | +```bash |
| 137 | +peanut [flags] <command> [args] |
| 138 | +``` |
28 | 139 |
|
29 | | -* The `CONFIGURE` transition may be triggered both with and without runtime configuration data, which |
30 | | -may or may not be suitable depending on user code. All other transitions send no payload. |
| 140 | +| Flag | Default | Description | |
| 141 | +|------|---------|-------------| |
| 142 | +| `-addr` | `localhost:47100` | gRPC address `host:port` | |
| 143 | +| `-mode` | `fmq` | `fmq` (JSON codec) or `direct` (protobuf) | |
| 144 | +| `-timeout` | `30s` | timeout for unary gRPC calls | |
| 145 | +| `-config` | `""` | path to YAML/JSON file; flattened key=value pairs are sent as arguments. Inline `key=val` arguments take precedence. | |
| 146 | + |
| 147 | +### Commands |
| 148 | + |
| 149 | +#### `get-state` |
| 150 | + |
| 151 | +Print the current FSM state. |
| 152 | + |
| 153 | +```bash |
| 154 | +peanut -addr localhost:47100 get-state |
| 155 | +``` |
| 156 | + |
| 157 | +#### `transition <fromState> <toState> [key=val ...]` |
| 158 | + |
| 159 | +High-level state transition. In `fmq` mode drives the full multi-step FairMQ sequence automatically. |
| 160 | + |
| 161 | +```bash |
| 162 | +# FairMQ: drive full configure sequence |
| 163 | +peanut -addr localhost:47100 -mode fmq transition STANDBY CONFIGURED \ |
| 164 | + chans.data.0.address=ipc://@o2ipc-example |
| 165 | +
|
| 166 | +# FairMQ: with config file |
| 167 | +peanut -addr localhost:47100 -mode fmq -config stfsender-configure-args.yaml \ |
| 168 | + transition STANDBY CONFIGURED |
| 169 | +
|
| 170 | +# Direct OCC |
| 171 | +peanut -addr localhost:47100 -mode direct transition STANDBY CONFIGURED |
| 172 | +``` |
| 173 | + |
| 174 | +FairMQ sequences driven automatically: |
| 175 | + |
| 176 | +| From → To | Steps | |
| 177 | +|-----------|-------| |
| 178 | +| `STANDBY → CONFIGURED` | INIT DEVICE, COMPLETE INIT, BIND, CONNECT, INIT TASK | |
| 179 | +| `CONFIGURED → RUNNING` | RUN | |
| 180 | +| `RUNNING → CONFIGURED` | STOP | |
| 181 | +| `CONFIGURED → STANDBY` | RESET TASK, RESET DEVICE | |
| 182 | + |
| 183 | +#### `direct-step <srcState> <event> [key=val ...]` |
| 184 | + |
| 185 | +Low-level: send a single raw OCC gRPC Transition call (protobuf codec). |
| 186 | + |
| 187 | +```bash |
| 188 | +peanut -addr localhost:47100 -mode direct direct-step STANDBY CONFIGURE key=val |
| 189 | +``` |
| 190 | + |
| 191 | +Events: `CONFIGURE`, `RESET`, `START`, `STOP`, `RECOVER`, `EXIT` |
| 192 | + |
| 193 | +#### `fmq-step <srcFMQState> <fmqEvent> [key=val ...]` |
| 194 | + |
| 195 | +Low-level: send a single raw FairMQ gRPC Transition call (JSON codec). |
| 196 | +State/event names that contain spaces must be quoted. |
| 197 | + |
| 198 | +```bash |
| 199 | +peanut -addr localhost:47100 fmq-step IDLE "INIT DEVICE" chans.x.0.address=ipc://@foo |
| 200 | +peanut -addr localhost:47100 fmq-step READY RUN |
| 201 | +``` |
| 202 | + |
| 203 | +#### `state-stream` |
| 204 | + |
| 205 | +Subscribe to `StateStream` and print state updates until interrupted (Ctrl-C). |
| 206 | + |
| 207 | +```bash |
| 208 | +peanut -addr localhost:47100 state-stream |
| 209 | +``` |
| 210 | + |
| 211 | +#### `event-stream` |
| 212 | + |
| 213 | +Subscribe to `EventStream` and print events until interrupted (Ctrl-C). |
| 214 | + |
| 215 | +```bash |
| 216 | +peanut -addr localhost:47100 event-stream |
| 217 | +``` |
31 | 218 |
|
32 | | -The last two commands are **not** transitions: |
| 219 | +--- |
33 | 220 |
|
34 | | -* `Load configuration` allows the user to read in a JSON or YAML file containing sample |
35 | | -configuration data that is then available to be pushed to the controlled process during a future |
36 | | -`CONFIGURE` transition. On startup, there is no file loaded, so a `CONFIGURE` transition will push |
37 | | -an empty payload. Once a runtime configuration file is loaded, its title bar reports `NOT PUSHED` |
38 | | -until the next `CONFIGURE` transition, at which point it becomes `PUSHED`. |
| 221 | +## Limitations |
39 | 222 |
|
40 | | -* `Quit` disconnects from the controlled process and quits `peanut`, but it performs no transitions |
41 | | -or other data exchange with the controlled process. A future instance of `peanut` may reattach itself |
42 | | -to the same process and continue from there. |
| 223 | +* The `GO_ERROR` transition cannot be triggered from `peanut`, as it is only triggered from user code inside the controlled process. |
| 224 | +* `Quit` / `q` disconnects without sending any transition. A future instance of `peanut` can reattach to the same process and continue. |
0 commit comments