feat(patterns,api): pattern OTA, graceful shutdown, driver delivery updates
- Pattern controller/UI and presets patterns tab for OTA to Wi-Fi drivers - Device controller extensions; driver_delivery chunk handling - main: SIGINT/SIGTERM shutdown, TCP/UDP server close coordination - Submodule led-driver: Wi-Fi default transport, lazy espnow import, dynamic patterns Made-with: Cursor
This commit is contained in:
@@ -240,6 +240,9 @@
|
||||
<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>
|
||||
@@ -247,6 +250,78 @@
|
||||
</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 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 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" 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">
|
||||
|
||||
Reference in New Issue
Block a user