@ctrlpi/ctrlpi-lab 0.0.0-stage → 0.9.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 ctrlPi
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,193 @@
1
- # Temporary Holding Version
1
+ # ctrlPi Lab
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ [![Platform: Cross-Platform](https://img.shields.io/badge/platform-Cross--Platform-006400.svg)](#quick-start)
4
+ [![Version 0.9.26](https://img.shields.io/badge/version-0.9.26-blue.svg)](https://github.com/ctrlpi/ctrlpi-lab/tags)
5
+ [![Node.js 20+](https://img.shields.io/badge/node.js-20%2B-blue.svg)](https://nodejs.org/)
6
+ [![Auth: Api-Key](https://img.shields.io/badge/auth-Api--Key-orange.svg)](#usage)
7
+ [![License: MIT](https://img.shields.io/badge/license-MIT-188038.svg)](LICENSE)
8
+ ![Status: Beta](https://img.shields.io/badge/status-Beta-red.svg)
9
+ [![CI](https://github.com/ctrlpi/ctrlpi-lab/actions/workflows/ci.yml/badge.svg)](https://github.com/ctrlpi/ctrlpi-lab/actions/workflows/ci.yml)
10
+
11
+ A local browser dashboard for your ctrlPi setup. Test GPIO and sensor endpoints,
12
+ watch webhook events, and tail agent logs, with zero dependencies.
13
+
14
+ Runs on **macOS, Linux, and Windows** with **Node.js 20+**. The dashboard connects
15
+ to an agent’s REST API; install `pi-gpio-api`, `pico-gpio-api`, or `esp32-gpio-api` on your board separately.
16
+
17
+ ## Quick start
18
+
19
+ Requires Node.js 20 or newer.
20
+
21
+ ```sh
22
+ npx @ctrlpi/ctrlpi-lab
23
+ ```
24
+
25
+ Your browser will open automatically at [http://localhost:7474](http://localhost:7474).
26
+
27
+ Or run directly from source without installing dependencies:
28
+
29
+ ```bash
30
+ git clone https://github.com/ctrlpi/ctrlpi-lab.git
31
+ cd ctrlpi-lab
32
+ node ctrlpi-lab.js
33
+ ```
34
+
35
+ By default, the dashboard listens only on the local computer (`127.0.0.1`). To allow LAN
36
+ devices to connect, pass `--host 0.0.0.0` (LAN access exposes the dashboard’s agent credentials and unrestricted proxy to those devices). Use `--no-open` to skip opening a browser, or `PORT=9000` to select a different port.
37
+
38
+ ## Discovery
39
+
40
+ At startup, ctrlpi-lab scans the local /24 for agents. If the shared config was updated within
41
+ the last five minutes, it checks saved agents for reachability instead. On page load, the dashboard selects localhost on the configured agent port if `/hello` responds;
42
+ otherwise it connects to the first responding agent immediately and keeps scanning in the background.
43
+ Agent choices remain sorted alphabetically.
44
+ Automatically discovered agents are saved with the default `Api-Key` only if that key works
45
+ (otherwise with none). Scanning preserves existing saved keys. The **+** form checks reachability
46
+ and verifies a supplied key through the backend proxy before saving.
47
+
48
+ ## Usage
49
+
50
+ 1. Select an agent from the header dropdown, scan with the network icon, or click
51
+ **+** to enter its IP/hostname, port (default **8314**), and API key.
52
+ 2. Choose an endpoint in the **API** sidebar. Fill in its parameters and send the
53
+ request to see the response. The key icon edits the saved connection key.
54
+ 3. Open **Logs** to search the agent’s output, or **Webhooks** to inspect the public
55
+ ctrlpi.com test feed when that target is configured on your agent.
56
+
57
+ The **Welcome to ctrlPi** panel includes Pi, Pico, and ESP32 installation steps.
58
+ **API - cURL Examples** provides nine commands using your selected address and key.
59
+
60
+ ### Examples
61
+
62
+ | Task | API endpoint | Parameters or body |
63
+ |---|---|---|
64
+ | Check whether an agent is online | `GET /hello` | No API key required |
65
+ | Read configured GPIO pins | `GET /gpio/read` | No body |
66
+ | Set GPIO 26 HIGH | `POST /gpio/write/26` | `{"value": 1}` |
67
+ | Pulse GPIO 26 for two seconds | `POST /gpio/write/26` | `{"value": 1, "duration": 2}` |
68
+ | Configure a watched input | `POST /gpio/config/6` | `{"type": "input", "watched": true}` |
69
+ | Configure a Pi sensor | `POST /sensor/config/cpu_temp` | `{"script": "cpu-temp.sh"}` |
70
+ | Read that sensor | `GET /sensor/read/cpu_temp` | No body |
71
+
72
+ All endpoints except `/hello` require the agent’s API key. On a Pico, use
73
+ `cpu-temp.py` for the example sensor. Watched inputs send events when a webhook or
74
+ bridge target is configured; otherwise, the agent logs the events.
75
+
76
+ ## Configuration
77
+
78
+ Saved agents are stored in the shared `agents-config.json`'s `agents[]` (`{name, ip, port, api_key, updated_at}`), the
79
+ one list every ctrlpi project reads - add an agent here and `mcp-bridge`, `studio-bridge` and the
80
+ smart-home bridges all see it. This dashboard's own `lab-config.json` holds the rest: the agent it
81
+ is currently pointed at (`selected_agent: {ip, port}`, its key coming from that agent's `agents[]`
82
+ entry) and `online_agents` (what the last network scan
83
+ reached, retained as scan history; saved agents remain selectable), as `ip:port` strings. Every host uses the same
84
+ `ip` + `port` pair, never a URL.
85
+
86
+ > **Where the config lives:** in `~/.ctrlpi/`, always - never next to `ctrlpi-lab.js`, whatever way you
87
+ > started it. Two files: the shared **`~/.ctrlpi/agents-config.json`** holds `agents[]` (every ctrlpi project
88
+ > reads and updates that one list), and **`~/.ctrlpi/lab-config.json`** holds what only this dashboard
89
+ > owns (`selected_agent`, `online_agents`). Pass `--config <path>` (a `.json` file,
90
+ > or a directory to hold both) to put them anywhere else.
91
+ >
92
+ > When reading the shared agents, ctrlpi-lab also checks if `/var/lib/homebridge/ctrlpi-agents-config.json`
93
+ > exists; if so, it reads it (read-only) and reconciles agents whose `updated_at` is newer. It never writes to the Homebridge config file.
94
+
95
+ Both files are optional. For example, the shared `~/.ctrlpi/agents-config.json` can contain:
96
+
97
+ ```json
98
+ {
99
+ "agents": [
100
+ { "name": "garage-pi", "ip": "192.168.1.50", "port": 8314, "api_key": "your-secret-key" }
101
+ ]
102
+ }
103
+ ```
104
+
105
+ The dashboard’s `~/.ctrlpi/lab-config.json` stores its selected agent and scan history:
106
+
107
+ ```json
108
+ {
109
+ "selected_agent": { "ip": "192.168.1.50", "port": 8314 },
110
+ "online_agents": ["192.168.1.50:8314"]
111
+ }
112
+ ```
113
+
114
+ - The header shows the selected agent’s IP and port after its model. Use the arrow to choose a saved agent,
115
+ or the **+** button to add an IP/hostname, port, and API key. The key icon edits the selected agent’s key.
116
+ - Environment override: `API_KEY` sets the agent key.
117
+ - Discovered and last-used agents are saved back to the shared `~/.ctrlpi/agents-config.json` automatically,
118
+ so you don't have to edit it by hand.
119
+
120
+ ## Tabs
121
+
122
+ - **API**: test GPIO, sensor, and configuration endpoints. The sidebar's Get Started section has
123
+ **Welcome to ctrlPi** with Pi, Pico and ESP32 installation steps, nine **API - cURL Examples**
124
+ aligned with the Pi API README and populated with the selected address/key, and a **Pinouts**
125
+ link to the board pinouts on ctrlpi.com. Changing the
126
+ agent’s API key is available only in the red Danger Zone of Config Update.
127
+ - **Logs**: compact log viewer with text search. Webhook tags are orange.
128
+ Red trash and refresh icons sit immediately after the search box. Reset Log
129
+ asks for confirmation, sets the agent’s `log_days` to `0`, then restores the previous value.
130
+ - **Webhooks**: **Webhook Events** displays the public ctrlpi.com test feed when the selected
131
+ agent’s configured webhook URL contains `ctrlpi.com`. The refresh icon sits after the title.
132
+ This is a shared test feed, not a private per-agent event store.
133
+
134
+ Logs and Webhooks offer **3s, 10s, 20s (default), 30s, and Manual** polling, plus auto-scroll.
135
+ The header includes the agent picker, **+** button, saved-key editor, light/dark toggle,
136
+ status indicator, and network scan button.
137
+
138
+ ## How it works
139
+
140
+ The dashboard runs on Node's built-in HTTP server with zero runtime dependencies. Browser
141
+ requests to agents pass through `/api/proxy/url` using `piApiFetch`, avoiding CORS restrictions.
142
+ HTML assets in `pages/` are assembled and cached in memory. In development mode (`npm run dev`),
143
+ the header’s **Reload page cache** icon rebuilds the cache and reloads the page.
144
+
145
+ The dashboard answers only requests addressed to an IP address, `localhost`, this computer's
146
+ own name (or `<name>.local`) or the `--host` value, and only from its own page. A website you
147
+ visit cannot read your agent keys or reach your agents through it.
148
+
149
+ ## Tests and CI
150
+
151
+ Requires Node 20+ and Python 3 (`python3`, or set `PYTHON` to its executable). Python is needed only for the mock-agent tests.
152
+
153
+ ```bash
154
+ npm test # unit tests + mock-agent HTTP integration tests
155
+ ```
156
+
157
+ Integration tests launch the real lab server and a local copy of
158
+ `ctrlpi-cli/mock_agent.py` on OS-assigned loopback ports. They use a temporary
159
+ `--config` directory, preserve unrelated shared-config fields, and stop child
160
+ processes and delete temporary configs after each run. No Pi, Pico, public webhook
161
+ service, real credentials, or user configuration is needed. The fixture is the same
162
+ `mock_agent.py` the other ctrlPi projects test against.
163
+
164
+ The lab supports `--no-open` to skip opening a browser and `--no-startup-scan`
165
+ to skip automatic discovery. Tests use both, plus `HOST=127.0.0.1` and `PORT=0`.
166
+
167
+ No npm installation is needed for the app or tests. CI runs all nine combinations
168
+ of Node 22, 24, and 26 with macOS, Linux (Ubuntu), and Windows. Each job starts the
169
+ real lab server and the mock agent. There is no coverage reporting or coverage gate.
170
+
171
+ Tests cover agent discovery/selection, adding agents, credentials, real proxy
172
+ requests, the Host and Origin check, GPIO write/read state and form values, sensors,
173
+ configuration persistence, logs, and webhook rendering. Dashboard tests use a small DOM stub, not a browser. Hardware
174
+ timing/electrical behavior, real LAN discovery, external webhook delivery, and visual
175
+ layout remain outside this suite. The mock
176
+ agent approximates the REST contract; it does not replace tests on real hardware.
177
+
178
+ ## Related projects
179
+
180
+ - **[`pi-gpio-api`](https://github.com/ctrlpi/pi-gpio-api)**: Raspberry Pi GPIO REST server that reads inputs and drives outputs (and named sensors) over an HTTP API.
181
+ - **[`pico-gpio-api`](https://github.com/ctrlpi/pico-gpio-api)**: Raspberry Pi Pico W port of the GPIO REST server, with the same endpoints, wire format, and auth.
182
+ - **[`esp32-gpio-api`](https://github.com/ctrlpi/esp32-gpio-api)**: ESP32 port of the GPIO REST server for MicroPython, with the same endpoints, wire format, and auth.
183
+ - **[`mcp-bridge`](https://github.com/ctrlpi/mcp-bridge)**: MCP server that exposes GPIO control as tools for AI agents (e.g. Claude), executing them over the agents' REST API.
184
+ - **[`homebridge-ctrlpi`](https://github.com/ctrlpi/homebridge-ctrlpi)**: A Homebridge plugin that brings Raspberry Pi, Pico W, and ESP32 GPIO into Apple Home, by driving one or more GPIO agents over their REST API.
185
+ - **`homekit-bridge`** *(coming soon)*: Native Apple HomeKit bridge that exposes GPIO pins and sensors as HomeKit accessories, driven over the agents' REST API.
186
+ - **`matter-bridge`** *(coming soon)*: Matter bridge that exposes GPIO pins and sensors to any Matter platform (Apple Home, Google Home, Alexa, Home Assistant), driven over the agents' REST API.
187
+ - **[`ctrlpi-cli`](https://github.com/ctrlpi/ctrlpi-cli)**: Command-line interface for interacting with ctrlPi agents, with shared agent configuration.
188
+ - **[`pico-bay`](https://github.com/ctrlpi/pico-bay)**: Web app and MCP server for managing MicroPython and CircuitPython boards, such as the Raspberry Pi Pico and ESP32, over USB.
189
+ - **`pi-bay`** *(coming soon)*: A local web app and MCP server for Raspberry Pi boards over the network. Edit files, open a remote terminal, and manage your Pi remotely.
190
+
191
+ ## License
192
+
193
+ [MIT](LICENSE)