538 lines
30 KiB
HTML
538 lines
30 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>LED Controller - Zone Mode</title>
|
||
<link rel="stylesheet" href="/static/style.css">
|
||
</head>
|
||
<body>
|
||
<div class="app-container">
|
||
<header>
|
||
<div class="zones-container">
|
||
<div id="zones-list">
|
||
Loading zones...
|
||
</div>
|
||
</div>
|
||
<div class="header-actions">
|
||
<button class="btn btn-secondary" id="profiles-btn">Profiles</button>
|
||
<button class="btn btn-secondary edit-mode-only" id="devices-btn">Devices</button>
|
||
<button class="btn btn-secondary edit-mode-only" id="zones-btn">Zones</button>
|
||
<button class="btn btn-secondary edit-mode-only" id="presets-btn">Presets</button>
|
||
<button class="btn btn-secondary edit-mode-only" id="patterns-btn">Patterns</button>
|
||
<button class="btn btn-secondary edit-mode-only" id="color-palette-btn">Colour Palette</button>
|
||
<button class="btn btn-secondary edit-mode-only" id="send-profile-presets-btn">Send Presets</button>
|
||
<button class="btn btn-secondary edit-mode-only" id="led-tool-btn">LED Tool</button>
|
||
<button class="btn btn-secondary" id="help-btn">Help</button>
|
||
<button type="button" class="btn btn-secondary ui-mode-toggle" id="ui-mode-toggle" aria-pressed="false" title="Switch preset strip mode — label is the mode you will switch to">Edit mode</button>
|
||
</div>
|
||
<div class="header-menu-mobile">
|
||
<button class="btn btn-secondary" id="main-menu-btn">Menu</button>
|
||
<div id="main-menu-dropdown" class="main-menu-dropdown">
|
||
<button type="button" class="ui-mode-toggle" id="ui-mode-toggle-mobile" aria-pressed="false">Edit mode</button>
|
||
<button type="button" data-target="profiles-btn">Profiles</button>
|
||
<button type="button" class="edit-mode-only" data-target="devices-btn">Devices</button>
|
||
<button type="button" class="edit-mode-only" data-target="zones-btn">Tabs</button>
|
||
<button type="button" class="edit-mode-only" data-target="presets-btn">Presets</button>
|
||
<button type="button" class="edit-mode-only" data-target="patterns-btn">Patterns</button>
|
||
<button type="button" class="edit-mode-only" data-target="color-palette-btn">Colour Palette</button>
|
||
<button type="button" class="edit-mode-only" data-target="send-profile-presets-btn">Send Presets</button>
|
||
<button type="button" class="edit-mode-only" data-target="led-tool-btn">LED Tool</button>
|
||
<button type="button" data-target="help-btn">Help</button>
|
||
</div>
|
||
</div>
|
||
</header>
|
||
|
||
<div class="main-content">
|
||
<div id="zone-content" class="zone-content">
|
||
<div class="zone-content-placeholder">
|
||
Select a zone to get started
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Tabs Modal -->
|
||
<div id="zones-modal" class="modal">
|
||
<div class="modal-content">
|
||
<h2>Tabs</h2>
|
||
<div class="profiles-actions zone-modal-create-row">
|
||
<input type="text" id="new-zone-name" placeholder="Zone name">
|
||
<button class="btn btn-primary" id="create-zone-btn">Create</button>
|
||
</div>
|
||
<div id="zones-list-modal" class="profiles-list"></div>
|
||
<div class="modal-actions">
|
||
<button class="btn btn-secondary" id="zones-close-btn">Close</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Edit Zone Modal -->
|
||
<div id="edit-zone-modal" class="modal">
|
||
<div class="modal-content">
|
||
<h2>Edit Zone</h2>
|
||
<form id="edit-zone-form">
|
||
<input type="hidden" id="edit-zone-id">
|
||
<div class="modal-actions" style="margin-bottom: 1rem;">
|
||
<button type="submit" class="btn btn-primary">Save</button>
|
||
<button type="button" class="btn btn-secondary" onclick="document.getElementById('edit-zone-modal').classList.remove('active')">Close</button>
|
||
</div>
|
||
<label>Zone Name:</label>
|
||
<input type="text" id="edit-zone-name" placeholder="Enter zone name" required>
|
||
<label class="zone-devices-label">Devices in this zone</label>
|
||
<div id="edit-zone-devices-editor" class="zone-devices-editor"></div>
|
||
<label class="zone-presets-section-label">Presets on this zone</label>
|
||
<div id="edit-zone-presets-current" class="profiles-list edit-zone-presets-scroll"></div>
|
||
<label class="zone-presets-section-label">Add presets to this zone</label>
|
||
<div id="edit-zone-presets-list" class="profiles-list edit-zone-presets-scroll"></div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Profiles Modal -->
|
||
<div id="profiles-modal" class="modal">
|
||
<div class="modal-content">
|
||
<h2>Profiles</h2>
|
||
<div class="profiles-actions">
|
||
<input type="text" id="new-profile-name" placeholder="Profile name">
|
||
<button class="btn btn-primary" id="create-profile-btn">Create</button>
|
||
</div>
|
||
<div class="form-group" style="margin-top: 0.5rem; margin-bottom: 0;">
|
||
<label style="display: flex; align-items: center; gap: 0.5rem; margin-bottom: 0;">
|
||
<input type="checkbox" id="new-profile-seed-dj">
|
||
DJ zone
|
||
</label>
|
||
</div>
|
||
<div id="profiles-list" class="profiles-list"></div>
|
||
<div class="modal-actions">
|
||
<button class="btn btn-secondary" id="profiles-close-btn">Close</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Devices Modal (registry: Wi-Fi drivers appear when they connect over TCP) -->
|
||
<div id="devices-modal" class="modal">
|
||
<div class="modal-content">
|
||
<h2>Devices</h2>
|
||
<div id="devices-list-modal" class="profiles-list"></div>
|
||
<div class="modal-actions">
|
||
<button type="button" class="btn btn-secondary" id="devices-close-btn">Close</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="edit-device-modal" class="modal">
|
||
<div class="modal-content">
|
||
<h2>Edit device</h2>
|
||
<form id="edit-device-form">
|
||
<input type="hidden" id="edit-device-id">
|
||
<p class="muted-text" style="margin-bottom:0.75rem;">MAC (id): <code id="edit-device-storage-id"></code></p>
|
||
<label for="edit-device-name">Name</label>
|
||
<input type="text" id="edit-device-name" required autocomplete="off">
|
||
<label for="edit-device-type" style="margin-top:0.75rem;display:block;">Type</label>
|
||
<select id="edit-device-type">
|
||
<option value="led">LED</option>
|
||
</select>
|
||
<label for="edit-device-transport" style="margin-top:0.75rem;display:block;">Transport</label>
|
||
<select id="edit-device-transport">
|
||
<option value="espnow">ESP-NOW</option>
|
||
<option value="wifi">WiFi</option>
|
||
</select>
|
||
<div id="edit-device-address-espnow" style="margin-top:0.75rem;">
|
||
<label class="device-field-label">MAC (12 hex, optional)</label>
|
||
<div id="edit-device-address-boxes" class="hex-address-row" aria-label="MAC address"></div>
|
||
</div>
|
||
<div id="edit-device-address-wifi-wrap" style="margin-top:0.75rem;" hidden>
|
||
<label for="edit-device-address-wifi">Address (IP or hostname)</label>
|
||
<input type="text" id="edit-device-address-wifi" placeholder="192.168.1.50" autocomplete="off">
|
||
</div>
|
||
<div class="modal-actions">
|
||
<button type="submit" class="btn btn-primary">Save</button>
|
||
<button type="button" class="btn btn-secondary" id="edit-device-close-btn">Cancel</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Presets Modal -->
|
||
<div id="presets-modal" class="modal">
|
||
<div class="modal-content">
|
||
<h2>Presets</h2>
|
||
<div class="modal-actions">
|
||
<button class="btn btn-primary" id="preset-add-btn">Add</button>
|
||
</div>
|
||
<div id="presets-list" class="profiles-list"></div>
|
||
<div class="modal-actions">
|
||
<button class="btn btn-secondary" id="presets-close-btn">Close</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Preset Editor Modal -->
|
||
<div id="preset-editor-modal" class="modal">
|
||
<div class="modal-content">
|
||
<h2>Preset</h2>
|
||
<div class="profiles-actions">
|
||
<input type="text" id="preset-name-input" placeholder="Preset name">
|
||
<select id="preset-pattern-input">
|
||
<option value="">Pattern</option>
|
||
</select>
|
||
</div>
|
||
<label>Colours</label>
|
||
<div id="preset-colors-container" class="preset-colors-container"></div>
|
||
<div class="profiles-actions">
|
||
<input type="color" id="preset-new-color" value="#ffffff" title="Choose colour (auto-adds)">
|
||
<button class="btn btn-secondary btn-small" id="preset-add-from-palette-btn">From Palette</button>
|
||
</div>
|
||
<div class="profiles-actions">
|
||
<div class="preset-editor-field">
|
||
<label for="preset-brightness-input">Brightness (0–255)</label>
|
||
<input type="number" id="preset-brightness-input" placeholder="Brightness" min="0" max="255" value="0">
|
||
</div>
|
||
<div class="preset-editor-field">
|
||
<label for="preset-delay-input">Delay (ms)</label>
|
||
<input type="number" id="preset-delay-input" placeholder="Delay" min="0" max="10000" value="0">
|
||
</div>
|
||
</div>
|
||
<div class="n-params-grid">
|
||
<div class="n-param-group">
|
||
<label for="preset-n1-input" id="preset-n1-label">n1:</label>
|
||
<input type="number" id="preset-n1-input" min="0" max="255" value="0" class="n-input">
|
||
</div>
|
||
<div class="n-param-group">
|
||
<label for="preset-n2-input" id="preset-n2-label">n2:</label>
|
||
<input type="number" id="preset-n2-input" min="0" max="255" value="0" class="n-input">
|
||
</div>
|
||
<div class="n-param-group">
|
||
<label for="preset-n3-input" id="preset-n3-label">n3:</label>
|
||
<input type="number" id="preset-n3-input" min="0" max="255" value="0" class="n-input">
|
||
</div>
|
||
<div class="n-param-group">
|
||
<label for="preset-n4-input" id="preset-n4-label">n4:</label>
|
||
<input type="number" id="preset-n4-input" min="0" max="255" value="0" class="n-input">
|
||
</div>
|
||
<div class="n-param-group">
|
||
<label for="preset-n5-input" id="preset-n5-label">n5:</label>
|
||
<input type="number" id="preset-n5-input" min="0" max="255" value="0" class="n-input">
|
||
</div>
|
||
<div class="n-param-group">
|
||
<label for="preset-n6-input" id="preset-n6-label">n6:</label>
|
||
<input type="number" id="preset-n6-input" min="0" max="255" value="0" class="n-input">
|
||
</div>
|
||
<div class="n-param-group">
|
||
<label for="preset-n7-input" id="preset-n7-label">n7:</label>
|
||
<input type="number" id="preset-n7-input" min="0" max="255" value="0" class="n-input">
|
||
</div>
|
||
<div class="n-param-group">
|
||
<label for="preset-n8-input" id="preset-n8-label">n8:</label>
|
||
<input type="number" id="preset-n8-input" min="0" max="255" value="0" class="n-input">
|
||
</div>
|
||
</div>
|
||
<div class="modal-actions preset-editor-modal-actions">
|
||
<button class="btn btn-secondary" id="preset-send-btn">Try</button>
|
||
<button class="btn btn-secondary" id="preset-default-btn">Default</button>
|
||
<button type="button" class="btn btn-danger" id="preset-remove-from-zone-btn" hidden>Remove from zone</button>
|
||
<button class="btn btn-primary" id="preset-save-btn">Save & Send</button>
|
||
<button class="btn btn-secondary" id="preset-editor-close-btn">Close</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Patterns Modal -->
|
||
<div id="patterns-modal" class="modal">
|
||
<div class="modal-content">
|
||
<h2>Patterns</h2>
|
||
<div class="modal-actions">
|
||
<button type="button" class="btn btn-primary" id="pattern-add-btn">Add</button>
|
||
</div>
|
||
<div id="patterns-list" class="profiles-list"></div>
|
||
<div class="modal-actions">
|
||
<button class="btn btn-secondary" id="patterns-close-btn">Close</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Pattern Editor Modal -->
|
||
<div id="pattern-editor-modal" class="modal">
|
||
<div class="modal-content">
|
||
<h2>Pattern</h2>
|
||
<p class="muted-text" style="margin: 0 0 0.75rem 0;">Add a driver <code>.py</code> file and editor metadata (stored in the pattern database).</p>
|
||
<div class="profiles-row" style="flex-wrap: wrap; gap: 0.5rem; margin-bottom: 0.5rem;">
|
||
<label for="pattern-create-name" style="min-width: 7rem;">Name</label>
|
||
<input type="text" id="pattern-create-name" class="preset-name-like" placeholder="e.g. sparkle" pattern="[a-zA-Z_][a-zA-Z0-9_]*" style="flex: 1; min-width: 12rem;" autocomplete="off">
|
||
</div>
|
||
<div id="pattern-create-n-section" class="n-params-section" style="margin-bottom: 0.5rem;">
|
||
<h3 class="muted-text">Readable parameter names</h3>
|
||
<p id="pattern-create-n-empty" class="muted-text" style="display: none; margin: 0 0 0.5rem 0;">No parameter names are stored for this pattern.</p>
|
||
<div class="n-params-grid">
|
||
<div class="n-param-group">
|
||
<label for="pattern-create-n1"></label>
|
||
<input type="text" id="pattern-create-n1" class="n-input pattern-n-readable-input" placeholder="" autocomplete="off">
|
||
</div>
|
||
<div class="n-param-group">
|
||
<label for="pattern-create-n2"></label>
|
||
<input type="text" id="pattern-create-n2" class="n-input pattern-n-readable-input" placeholder="" autocomplete="off">
|
||
</div>
|
||
<div class="n-param-group">
|
||
<label for="pattern-create-n3"></label>
|
||
<input type="text" id="pattern-create-n3" class="n-input pattern-n-readable-input" placeholder="" autocomplete="off">
|
||
</div>
|
||
<div class="n-param-group">
|
||
<label for="pattern-create-n4"></label>
|
||
<input type="text" id="pattern-create-n4" class="n-input pattern-n-readable-input" placeholder="" autocomplete="off">
|
||
</div>
|
||
<div class="n-param-group">
|
||
<label for="pattern-create-n5"></label>
|
||
<input type="text" id="pattern-create-n5" class="n-input pattern-n-readable-input" placeholder="" autocomplete="off">
|
||
</div>
|
||
<div class="n-param-group">
|
||
<label for="pattern-create-n6"></label>
|
||
<input type="text" id="pattern-create-n6" class="n-input pattern-n-readable-input" placeholder="" autocomplete="off">
|
||
</div>
|
||
<div class="n-param-group">
|
||
<label for="pattern-create-n7"></label>
|
||
<input type="text" id="pattern-create-n7" class="n-input pattern-n-readable-input" placeholder="" autocomplete="off">
|
||
</div>
|
||
<div class="n-param-group">
|
||
<label for="pattern-create-n8"></label>
|
||
<input type="text" id="pattern-create-n8" class="n-input pattern-n-readable-input" placeholder="" autocomplete="off">
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="profiles-row pattern-editor-meta-row" style="flex-wrap: wrap; gap: 0.5rem; margin-bottom: 0.5rem;">
|
||
<label for="pattern-create-min-delay" style="min-width: 7rem;">Min delay (ms)</label>
|
||
<input type="number" id="pattern-create-min-delay" min="0" value="10">
|
||
<label for="pattern-create-max-delay">Max delay (ms)</label>
|
||
<input type="number" id="pattern-create-max-delay" min="0" value="10000">
|
||
<label for="pattern-create-max-colors">Max colours</label>
|
||
<input type="number" id="pattern-create-max-colors" min="0" value="10">
|
||
</div>
|
||
<div class="profiles-row" style="flex-direction: column; align-items: stretch; gap: 0.35rem; margin-bottom: 0.5rem;">
|
||
<label for="pattern-create-file">Pattern file</label>
|
||
<input type="file" id="pattern-create-file" accept=".py,text/x-python,.PY">
|
||
<label for="pattern-create-code" class="muted-text" style="font-size: 0.85em;">Or paste Python source (if no file chosen)</label>
|
||
<textarea id="pattern-create-code" rows="5" style="width: 100%; font-family: monospace; font-size: 0.85rem;" placeholder="# class MyPattern: ..."></textarea>
|
||
</div>
|
||
<div class="modal-actions">
|
||
<label style="display: inline-flex; align-items: center; gap: 0.35rem; margin-right: auto;">
|
||
<input type="checkbox" id="pattern-create-overwrite" checked>
|
||
<span>Overwrite existing file</span>
|
||
</label>
|
||
<button type="button" class="btn btn-primary" id="pattern-create-btn">Save</button>
|
||
<button type="button" class="btn btn-secondary" id="pattern-editor-close-btn">Close</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Colour Palette Modal -->
|
||
<div id="color-palette-modal" class="modal">
|
||
<div class="modal-content">
|
||
<h2>Colour Palette</h2>
|
||
<p class="muted-text">Profile: <span id="palette-current-profile-name">None</span></p>
|
||
<div id="palette-container" class="profiles-list"></div>
|
||
<div class="profiles-actions">
|
||
<input type="color" id="palette-new-color" value="#ffffff">
|
||
</div>
|
||
<div class="modal-actions">
|
||
<button class="btn btn-secondary" id="color-palette-close-btn">Close</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Help Modal -->
|
||
<div id="help-modal" class="modal">
|
||
<div class="modal-content">
|
||
<h2>Help</h2>
|
||
<p class="muted-text">How to use the LED controller UI.</p>
|
||
|
||
<h3>Run mode</h3>
|
||
<ul>
|
||
<li><strong>Select zone</strong>: left-click a zone button in the top bar.</li>
|
||
<li><strong>Select preset</strong>: left-click a preset tile to send a <code>select</code> message to all devices in the zone.</li>
|
||
<li><strong>Profiles</strong>: open <strong>Profiles</strong> to apply a profile. Profile editing actions are hidden in Run mode.</li>
|
||
<li><strong>Devices</strong>: open <strong>Devices</strong> to see drivers (Wi-Fi clients appear when they connect); edit or remove rows as needed.</li>
|
||
<li><strong>Send all presets</strong>: this action is available in <strong>Edit mode</strong> and pushes every preset used in the current zone to all zone devices.</li>
|
||
<li><strong>Switch modes</strong>: use the mode button in the menu. The button label shows the mode you will switch to.</li>
|
||
</ul>
|
||
|
||
<h3>Edit mode</h3>
|
||
<ul>
|
||
<li><strong>Tabs</strong>: create, edit, and manage tabs and device assignments.</li>
|
||
<li><strong>Presets</strong>: create/manage reusable presets and edit preset details.</li>
|
||
<li><strong>Preset tiles</strong>: each tile shows <strong>Edit</strong> and <strong>Remove</strong> controls in Edit mode.</li>
|
||
<li><strong>Reorder presets</strong>: drag and drop preset tiles to save zone order.</li>
|
||
<li><strong>Profiles</strong>: create/clone/delete profiles. New profiles get a populated <strong>default</strong> zone and can optionally seed a <strong>DJ zone</strong>.</li>
|
||
<li><strong>Devices</strong>: view, edit, or remove registry entries (tabs use <strong>names</strong>; each row is keyed by <strong>MAC</strong>).</li>
|
||
<li><strong>Colour Palette</strong>: build profile colours and use <strong>From Palette</strong> in preset editor to add linked colours (badge <strong>P</strong>) that update when palette colours change.</li>
|
||
</ul>
|
||
|
||
<h3>What led-tool does</h3>
|
||
<ul>
|
||
<li><strong>USB device setup</strong>: updates <code>settings.json</code> on ESP32 drivers over serial (for example name, pin, LED count, Wi-Fi credentials).</li>
|
||
<li><strong>Deploy and maintenance</strong>: uploads driver files, flashes firmware, resets device, and follows serial logs.</li>
|
||
<li><strong>Scope</strong>: led-tool configures devices directly; this web UI controls profiles/zones/presets and sends runtime messages.</li>
|
||
</ul>
|
||
|
||
<div class="modal-actions">
|
||
<button class="btn btn-secondary" id="help-close-btn">Close</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Settings Modal -->
|
||
<div id="settings-modal" class="modal">
|
||
<div class="modal-content">
|
||
<h2>Device Settings</h2>
|
||
<p class="muted-text">Configure WiFi Access Point and device settings.</p>
|
||
|
||
<div id="settings-message" class="message"></div>
|
||
|
||
<!-- Device Name -->
|
||
<div class="settings-section">
|
||
<h3>Device</h3>
|
||
<form id="device-form">
|
||
<div class="form-group">
|
||
<label for="device-name-input">Device Name</label>
|
||
<input type="text" id="device-name-input" name="device_name" placeholder="e.g. led-controller" required>
|
||
<small>This name may be used for mDNS (e.g. <code>name.local</code>) and UI display.</small>
|
||
</div>
|
||
<div class="form-group">
|
||
<label for="wifi-channel-input">WiFi channel (ESP-NOW)</label>
|
||
<input type="number" id="wifi-channel-input" name="wifi_channel" min="1" max="11" required>
|
||
<small>STA channel (1–11) for LED drivers and the serial bridge. Use the same value everywhere.</small>
|
||
</div>
|
||
<div class="btn-group">
|
||
<button type="submit" class="btn btn-primary btn-full">Save device settings</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
|
||
<!-- WiFi Access Point Settings -->
|
||
<div class="settings-section ap-settings-section">
|
||
<h3>WiFi Access Point</h3>
|
||
|
||
<div id="ap-status" class="status-info">
|
||
<h4>AP Status</h4>
|
||
<p>Loading...</p>
|
||
</div>
|
||
|
||
<form id="ap-form">
|
||
<div class="form-group">
|
||
<label for="ap-ssid">AP SSID (Network Name)</label>
|
||
<input type="text" id="ap-ssid" name="ssid" placeholder="Enter AP name" required>
|
||
<small>The name of the WiFi access point this device creates</small>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="ap-password">AP Password</label>
|
||
<input type="password" id="ap-password" name="password" placeholder="Enter AP password (min 8 chars)" data-bwignore>
|
||
<small>Leave empty for open network (min 8 characters if set)</small>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="ap-channel">Channel (1-11)</label>
|
||
<input type="number" id="ap-channel" name="channel" min="1" max="11" placeholder="Auto">
|
||
<small>WiFi channel (1-11 for 2.4GHz). Leave empty for auto.</small>
|
||
</div>
|
||
|
||
<div class="btn-group">
|
||
<button type="submit" class="btn btn-primary btn-full">Configure AP</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
|
||
<div class="modal-actions">
|
||
<button class="btn btn-secondary" id="settings-close-btn">Close</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- LED Tool Modal -->
|
||
<div id="led-tool-modal" class="modal">
|
||
<div class="modal-content">
|
||
<h2>LED Tool (USB)</h2>
|
||
<p class="muted-text" style="margin-top: 0;">Configure a driver connected over USB using <code>led-tool</code>.</p>
|
||
<div id="led-tool-message" class="message" style="margin-bottom: 0.75rem;"></div>
|
||
<form id="led-tool-form">
|
||
<div class="form-group">
|
||
<label for="led-tool-port">Serial port</label>
|
||
<div class="profiles-actions" style="gap: 0.5rem;">
|
||
<select id="led-tool-port" required style="flex:1;">
|
||
<option value="">Select a serial port</option>
|
||
</select>
|
||
<button type="button" class="btn btn-secondary" id="led-tool-refresh-ports-btn">Refresh</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="led-tool-name">Name</label>
|
||
<input type="text" id="led-tool-name" placeholder="led-abcdef123456">
|
||
</div>
|
||
<div class="profiles-actions">
|
||
<div class="preset-editor-field">
|
||
<label for="led-tool-num-leds">Num LEDs</label>
|
||
<input type="number" id="led-tool-num-leds" min="1" max="5000" placeholder="60">
|
||
</div>
|
||
<div class="preset-editor-field">
|
||
<label for="led-tool-led-pin">LED pin</label>
|
||
<input type="number" id="led-tool-led-pin" min="0" max="48" placeholder="4">
|
||
</div>
|
||
</div>
|
||
<div class="profiles-actions">
|
||
<div class="preset-editor-field">
|
||
<label for="led-tool-brightness">Brightness</label>
|
||
<input type="number" id="led-tool-brightness" min="0" max="255" placeholder="255">
|
||
</div>
|
||
<div class="preset-editor-field">
|
||
<label for="led-tool-wifi-channel">WiFi channel</label>
|
||
<input type="number" id="led-tool-wifi-channel" min="1" max="11" placeholder="6">
|
||
</div>
|
||
</div>
|
||
<div class="profiles-actions">
|
||
<div class="preset-editor-field">
|
||
<label for="led-tool-transport">Transport</label>
|
||
<select id="led-tool-transport">
|
||
<option value="">(no change)</option>
|
||
<option value="espnow">espnow</option>
|
||
<option value="wifi">wifi</option>
|
||
</select>
|
||
</div>
|
||
<div class="preset-editor-field">
|
||
<label for="led-tool-default">Default preset</label>
|
||
<input type="text" id="led-tool-default" placeholder="on">
|
||
</div>
|
||
</div>
|
||
<div class="form-group">
|
||
<label for="led-tool-ssid">SSID</label>
|
||
<input type="text" id="led-tool-ssid" placeholder="Your WiFi SSID">
|
||
</div>
|
||
<div class="form-group">
|
||
<label for="led-tool-password">WiFi password</label>
|
||
<input type="password" id="led-tool-password" placeholder="WiFi password">
|
||
</div>
|
||
|
||
<div class="modal-actions">
|
||
<button type="button" class="btn btn-secondary" id="led-tool-read-btn">Read</button>
|
||
<button type="button" class="btn btn-secondary" id="led-tool-reset-btn">Reset</button>
|
||
<button type="submit" class="btn btn-primary">Apply via USB</button>
|
||
<button type="button" class="btn btn-secondary" id="led-tool-close-btn">Close</button>
|
||
</div>
|
||
</form>
|
||
<label for="led-tool-output" style="margin-top:0.5rem; display:block;">Command output</label>
|
||
<textarea id="led-tool-output" rows="12" readonly style="width:100%; font-family:monospace; resize:vertical;"></textarea>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Styles moved to /static/style.css -->
|
||
<script src="/static/zones.js"></script>
|
||
<script src="/static/help.js"></script>
|
||
<script src="/static/led_tool.js"></script>
|
||
<script src="/static/color_palette.js"></script>
|
||
<script src="/static/profiles.js"></script>
|
||
<script src="/static/zone_palette.js"></script>
|
||
<script src="/static/patterns.js"></script>
|
||
<script src="/static/presets.js"></script>
|
||
<script src="/static/devices.js"></script>
|
||
</body>
|
||
</html>
|