@ctrlpi/ctrlpi-lab 0.0.0-stage → 0.9.25
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 +21 -0
- package/README.md +232 -2
- package/ctrlpi-lab.js +585 -0
- package/package.json +32 -4
- package/pages/Pico Pinout.html +186 -0
- package/pages/Raspberry Pi Pinout.html +184 -0
- package/pages/api.html +148 -0
- package/pages/api_curl.html +60 -0
- package/pages/logs.html +86 -0
- package/pages/main.html +5080 -0
- package/pages/webhooks.html +52 -0
- package/pages/welcome.html +83 -0
package/pages/api.html
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
<!-- PANE 1: OpenAPI Tester Screen -->
|
|
2
|
+
<div id="testerPane" class="pane active">
|
|
3
|
+
|
|
4
|
+
<!-- Left Side Endpoint Picker -->
|
|
5
|
+
<div class="sidebar">
|
|
6
|
+
<div class="sidebar-header">
|
|
7
|
+
<h3 class="sidebar-title">REST API Endpoints</h3>
|
|
8
|
+
<div class="search-box">
|
|
9
|
+
<!-- SVG Search -->
|
|
10
|
+
<svg viewBox="0 0 24 24">
|
|
11
|
+
<path
|
|
12
|
+
d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z" />
|
|
13
|
+
</svg>
|
|
14
|
+
<input type="text" id="endpointSearchInput" placeholder="Filter endpoints..."
|
|
15
|
+
oninput="filterEndpoints()">
|
|
16
|
+
</div>
|
|
17
|
+
</div>
|
|
18
|
+
|
|
19
|
+
<div class="endpoint-list" id="endpointList">
|
|
20
|
+
<!-- Dynamic Items -->
|
|
21
|
+
</div>
|
|
22
|
+
|
|
23
|
+
</div>
|
|
24
|
+
|
|
25
|
+
<!-- Right Side Workbench -->
|
|
26
|
+
<div class="workbench">
|
|
27
|
+
<div class="workbench-header">
|
|
28
|
+
<div class="workbench-path-row">
|
|
29
|
+
<div class="workbench-path-details">
|
|
30
|
+
<span id="selectedMethodBadge" class="method-badge get">GET</span>
|
|
31
|
+
<span id="selectedPathText" class="workbench-path-text">/api/endpoint</span>
|
|
32
|
+
</div>
|
|
33
|
+
</div>
|
|
34
|
+
<div class="workbench-description-row"
|
|
35
|
+
style="display: flex; justify-content: space-between; align-items: center; gap: 20px; margin-top: 10px; width: 100%;">
|
|
36
|
+
<p id="selectedDescriptionText" class="workbench-description"
|
|
37
|
+
style="margin-bottom: 0; flex-grow: 1;">Select an endpoint from the left menu to start
|
|
38
|
+
executing tests against your Raspberry Pi.</p>
|
|
39
|
+
<button id="sendRequestBtn" class="send-btn" onclick="sendApiRequest()" style="flex-shrink: 0;">
|
|
40
|
+
<!-- SVG Send -->
|
|
41
|
+
<svg width="18" height="18" fill="currentColor" viewBox="0 0 24 24">
|
|
42
|
+
<path d="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z" />
|
|
43
|
+
</svg>
|
|
44
|
+
Send
|
|
45
|
+
</button>
|
|
46
|
+
</div>
|
|
47
|
+
</div>
|
|
48
|
+
|
|
49
|
+
<div class="workbench-body focus-request">
|
|
50
|
+
|
|
51
|
+
<!-- Form inputs card -->
|
|
52
|
+
<div class="glass-card request-card">
|
|
53
|
+
<h3 class="workbench-section-title">
|
|
54
|
+
<!-- SVG Form / Edit -->
|
|
55
|
+
<svg viewBox="0 0 24 24">
|
|
56
|
+
<path
|
|
57
|
+
d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z" />
|
|
58
|
+
</svg>
|
|
59
|
+
Request
|
|
60
|
+
</h3>
|
|
61
|
+
|
|
62
|
+
<!-- Form builder container -->
|
|
63
|
+
<div class="params-form" id="paramsFormContainer">
|
|
64
|
+
<!-- Dynamic inputs loaded here -->
|
|
65
|
+
</div>
|
|
66
|
+
</div>
|
|
67
|
+
|
|
68
|
+
<!-- Output results card -->
|
|
69
|
+
<div class="glass-card response-card">
|
|
70
|
+
<h3 class="workbench-section-title">
|
|
71
|
+
<!-- SVG Console -->
|
|
72
|
+
<svg viewBox="0 0 24 24">
|
|
73
|
+
<path
|
|
74
|
+
d="M20 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm-5 14H4v-4h11v4zm5 0h-4v-4h4v4zm0-6H4V8h16v4z" />
|
|
75
|
+
</svg>
|
|
76
|
+
Response
|
|
77
|
+
</h3>
|
|
78
|
+
|
|
79
|
+
<!-- Empty State -->
|
|
80
|
+
<div id="responseEmptyState" class="response-empty-state">
|
|
81
|
+
<svg stroke="currentColor" viewBox="0 0 24 24">
|
|
82
|
+
<circle cx="12" cy="12" r="10" />
|
|
83
|
+
<path d="M12 16v-4" />
|
|
84
|
+
<path d="M12 8h.01" />
|
|
85
|
+
</svg>
|
|
86
|
+
<h3>No Active Response</h3>
|
|
87
|
+
<p>Select an endpoint, specify parameters, and click "Send" above to view raw server
|
|
88
|
+
responses and speed parameters here.</p>
|
|
89
|
+
</div>
|
|
90
|
+
|
|
91
|
+
<!-- Full Response details (hidden by default) -->
|
|
92
|
+
<div id="responseDetailsWrapper"
|
|
93
|
+
style="display: none; flex-grow: 1; flex-direction: column; overflow: hidden;">
|
|
94
|
+
<div class="response-meta-row">
|
|
95
|
+
<div class="resp-meta-item">
|
|
96
|
+
<span>Status:</span>
|
|
97
|
+
<span id="responseStatusBadge" class="resp-status-badge resp-status-2xx">200
|
|
98
|
+
OK</span>
|
|
99
|
+
</div>
|
|
100
|
+
<div class="resp-meta-item">
|
|
101
|
+
<span>Latency:</span>
|
|
102
|
+
<span id="responseLatencyVal" class="resp-meta-val">12 ms</span>
|
|
103
|
+
</div>
|
|
104
|
+
</div>
|
|
105
|
+
|
|
106
|
+
<div class="json-viewer-container">
|
|
107
|
+
<div class="json-viewer-header">
|
|
108
|
+
<span>BODY RESPONSE (application/json)</span>
|
|
109
|
+
<button class="copy-btn" onclick="copyResponseToClipboard()">
|
|
110
|
+
<svg viewBox="0 0 24 24">
|
|
111
|
+
<path
|
|
112
|
+
d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z" />
|
|
113
|
+
</svg>
|
|
114
|
+
Copy
|
|
115
|
+
</button>
|
|
116
|
+
</div>
|
|
117
|
+
<div id="jsonResponseView" class="json-content">
|
|
118
|
+
<!-- Colored JSON Output -->
|
|
119
|
+
</div>
|
|
120
|
+
</div>
|
|
121
|
+
|
|
122
|
+
<!-- Collapsible Headers -->
|
|
123
|
+
<div class="headers-toggle-wrapper">
|
|
124
|
+
<button class="headers-toggle-btn" onclick="toggleHeadersDropdown()">
|
|
125
|
+
<span>Response Headers</span>
|
|
126
|
+
<svg viewBox="0 0 24 24">
|
|
127
|
+
<path d="M7.41 8.59L12 13.17l4.59-4.58L18 10l-6 6-6-6 1.41-1.41z" />
|
|
128
|
+
</svg>
|
|
129
|
+
</button>
|
|
130
|
+
<div id="responseHeadersContent" class="headers-content"></div>
|
|
131
|
+
</div>
|
|
132
|
+
</div>
|
|
133
|
+
</div>
|
|
134
|
+
</div>
|
|
135
|
+
|
|
136
|
+
<!-- Pinout viewer (replaces workbench content when a pinout is selected) -->
|
|
137
|
+
<div id="pinoutPanel" style="display:none; flex-direction:column; flex:1; overflow:hidden; padding:0;">
|
|
138
|
+
<div style="display:flex; align-items:center; justify-content:space-between; padding:10px 20px; border-bottom:1px solid var(--border-muted); flex-shrink:0;">
|
|
139
|
+
<span id="pinoutLabel" style="font-size:0.95rem; font-weight:600; color:var(--text-main);"></span>
|
|
140
|
+
<button onclick="closePinout()" style="background:none; border:1px solid var(--border-muted); border-radius:6px; padding:4px 12px; cursor:pointer; color:var(--text-muted); font-size:0.8rem;">Close</button>
|
|
141
|
+
</div>
|
|
142
|
+
<iframe id="pinoutFrame" src="" style="flex:1; width:100%; border:none;" title="Pinout"></iframe>
|
|
143
|
+
</div>
|
|
144
|
+
|
|
145
|
+
<!--INCLUDE:pages/welcome.html-->
|
|
146
|
+
<!--INCLUDE:pages/api_curl.html-->
|
|
147
|
+
</div>
|
|
148
|
+
</div>
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
<div id="apiCurlPanel" class="info-panel">
|
|
2
|
+
<div class="info-panel-header">
|
|
3
|
+
<span class="info-panel-title">API - cURL Examples</span>
|
|
4
|
+
<button class="info-panel-close" onclick="closePinout()">Close</button>
|
|
5
|
+
</div>
|
|
6
|
+
<p style="font-size:0.85rem; color:var(--text-muted);">Examples use the current API URL and key from the header. All endpoints except <code>/hello</code> require the <code>Api-Key</code> header.</p>
|
|
7
|
+
|
|
8
|
+
<div class="info-section">
|
|
9
|
+
<h3>1. Health check</h3>
|
|
10
|
+
<p>Ping the Pi - no auth required. Used for discovery.</p>
|
|
11
|
+
<div class="info-code-block" id="curl1"></div>
|
|
12
|
+
</div>
|
|
13
|
+
|
|
14
|
+
<div class="info-section">
|
|
15
|
+
<h3>2. Read all configured pins</h3>
|
|
16
|
+
<p>Returns a dict of every pin that has been configured, with its current value and settings.</p>
|
|
17
|
+
<div class="info-code-block" id="curl2"></div>
|
|
18
|
+
</div>
|
|
19
|
+
|
|
20
|
+
<div class="info-section">
|
|
21
|
+
<h3>3. Write to a pin</h3>
|
|
22
|
+
<p>Set GPIO 26 HIGH for 2 seconds, then auto-revert. Pass <code>"value": 0</code> (or <code>"off"</code>) to set LOW, or <code>"value": "toggle"</code> to flip it.</p>
|
|
23
|
+
<div class="info-code-block" id="curl3"></div>
|
|
24
|
+
</div>
|
|
25
|
+
|
|
26
|
+
<div class="info-section">
|
|
27
|
+
<h3>4. Configure a pin (relay, reversed, max 1 hour)</h3>
|
|
28
|
+
<p>Name GPIO 26 "relay", set it as a reversed output with a 1-hour max pulse duration.</p>
|
|
29
|
+
<div class="info-code-block" id="curl4"></div>
|
|
30
|
+
</div>
|
|
31
|
+
|
|
32
|
+
<div class="info-section">
|
|
33
|
+
<h3>5. Scan all BCM GPIO hardware pins (Pi only)</h3>
|
|
34
|
+
<p>Read the physical state of the Pi’s BCM GPIO pins (requires Pi hardware). Returns <code>level</code> (physical) and <code>value</code> (logical, reversed-aware) for each pin.</p>
|
|
35
|
+
<div class="info-code-block" id="curl5"></div>
|
|
36
|
+
</div>
|
|
37
|
+
|
|
38
|
+
<div class="info-section">
|
|
39
|
+
<h3>6. Configure a watched input</h3>
|
|
40
|
+
<p>Set GPIO 6 as a watched input. State changes send webhooks when a target is configured; with no webhook or bridge target, events are logged instead.</p>
|
|
41
|
+
<div class="info-code-block" id="curl6"></div>
|
|
42
|
+
</div>
|
|
43
|
+
|
|
44
|
+
<div class="info-section">
|
|
45
|
+
<h3>7. Change the webhook URL</h3>
|
|
46
|
+
<p>Update where watched-pin events get POSTed.</p>
|
|
47
|
+
<div class="info-code-block" id="curl7"></div>
|
|
48
|
+
</div>
|
|
49
|
+
<div class="info-section">
|
|
50
|
+
<h3>8. Configure a sensor</h3>
|
|
51
|
+
<p>Configure <code>cpu_temp</code> using <code>cpu-temp.sh</code>, the example seeded into <code>scripts/</code> by the Pi installer. On a Pico, use <code>cpu-temp.py</code> instead.</p>
|
|
52
|
+
<div class="info-code-block" id="curl8"></div>
|
|
53
|
+
</div>
|
|
54
|
+
|
|
55
|
+
<div class="info-section">
|
|
56
|
+
<h3>9. Read a sensor</h3>
|
|
57
|
+
<p>Read the configured sensor. The result is returned under its name, for example <code>{"cpu_temp": 47.8}</code>.</p>
|
|
58
|
+
<div class="info-code-block" id="curl9"></div>
|
|
59
|
+
</div>
|
|
60
|
+
</div>
|
package/pages/logs.html
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
<div id="logPane" class="pane">
|
|
2
|
+
|
|
3
|
+
<!-- Controls toolbar -->
|
|
4
|
+
<div class="log-toolbar">
|
|
5
|
+
<div class="toolbar-left-group">
|
|
6
|
+
<div class="search-box log-search">
|
|
7
|
+
<svg viewBox="0 0 24 24">
|
|
8
|
+
<path
|
|
9
|
+
d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z" />
|
|
10
|
+
</svg>
|
|
11
|
+
<input type="text" id="logSearchInput" placeholder="Search logs..." oninput="fetchLogs()">
|
|
12
|
+
</div>
|
|
13
|
+
|
|
14
|
+
<div class="log-icon-actions">
|
|
15
|
+
<!-- Truncate Log File -->
|
|
16
|
+
<button type="button" class="key-icon-btn" title="Reset log" aria-label="Reset log" onclick="clearLogsOnServer()">
|
|
17
|
+
<svg aria-hidden="true" viewBox="0 0 24 24">
|
|
18
|
+
<path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z" />
|
|
19
|
+
</svg>
|
|
20
|
+
</button>
|
|
21
|
+
|
|
22
|
+
<!-- Manual Refresh -->
|
|
23
|
+
<button type="button" class="theme-toggle-btn" title="Refresh logs" aria-label="Refresh logs" onclick="triggerManualLogRefresh()">
|
|
24
|
+
<svg aria-hidden="true" id="refreshBtnIcon" viewBox="0 0 24 24">
|
|
25
|
+
<path
|
|
26
|
+
d="M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z" />
|
|
27
|
+
</svg>
|
|
28
|
+
</button>
|
|
29
|
+
</div>
|
|
30
|
+
|
|
31
|
+
<div class="log-count-badge">
|
|
32
|
+
Showing <span id="logLinesCount">0</span> log lines
|
|
33
|
+
</div>
|
|
34
|
+
</div>
|
|
35
|
+
|
|
36
|
+
<div class="toolbar-right-group">
|
|
37
|
+
|
|
38
|
+
<!-- Auto refresh rate -->
|
|
39
|
+
<div class="refresh-rate-group">
|
|
40
|
+
<label for="refreshRateSelect">Poll Rate:</label>
|
|
41
|
+
<select id="refreshRateSelect" class="refresh-rate-select" onchange="setupLogAutoRefresh()">
|
|
42
|
+
<option value="3000">3s</option>
|
|
43
|
+
<option value="10000">10s</option>
|
|
44
|
+
<option value="20000" selected>20s</option>
|
|
45
|
+
<option value="30000">30s</option>
|
|
46
|
+
<option value="manual">Manual</option>
|
|
47
|
+
</select>
|
|
48
|
+
</div>
|
|
49
|
+
|
|
50
|
+
<!-- Auto Scroll Toggle -->
|
|
51
|
+
<div class="config-input-group switch-group" style="border:none; padding:0; background:none;">
|
|
52
|
+
<label for="logAutoScrollToggle" style="margin-right: 6px;">Auto Scroll</label>
|
|
53
|
+
<label class="toggle-switch">
|
|
54
|
+
<input type="checkbox" id="logAutoScrollToggle" checked>
|
|
55
|
+
<span class="slider"></span>
|
|
56
|
+
</label>
|
|
57
|
+
</div>
|
|
58
|
+
|
|
59
|
+
</div>
|
|
60
|
+
</div>
|
|
61
|
+
|
|
62
|
+
<!-- Log Terminal box -->
|
|
63
|
+
<div class="terminal-container">
|
|
64
|
+
<div class="terminal-header">
|
|
65
|
+
<div class="terminal-dots">
|
|
66
|
+
<span class="terminal-dot td-red"></span>
|
|
67
|
+
<span class="terminal-dot td-yellow"></span>
|
|
68
|
+
<span class="terminal-dot td-green"></span>
|
|
69
|
+
</div>
|
|
70
|
+
<div class="terminal-title">GET /logs (polling)</div>
|
|
71
|
+
<div></div>
|
|
72
|
+
</div>
|
|
73
|
+
|
|
74
|
+
<div class="terminal-screen" id="logTerminalScreen">
|
|
75
|
+
<!-- Dynamic logs outputted here -->
|
|
76
|
+
<div class="logs-empty-state" id="logsEmptyState">
|
|
77
|
+
<svg stroke="currentColor" viewBox="0 0 24 24">
|
|
78
|
+
<path
|
|
79
|
+
d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
|
|
80
|
+
</svg>
|
|
81
|
+
<span>No log messages found on the server. Try running some tests!</span>
|
|
82
|
+
</div>
|
|
83
|
+
</div>
|
|
84
|
+
</div>
|
|
85
|
+
|
|
86
|
+
</div>
|