Per-frame palette calibration + sidebar battery indicator
Build and push server image / build-and-push (push) Successful in 40s
Build and push server image / build-and-push (push) Successful in 40s
Advanced configuration (Configuration tab, collapsed <details> section):
a color picker per ink color (black/white/yellow/red/blue/green),
overriding image_pipeline.DEFAULT_PALETTE_RGB for that frame's actual
panel -- different units can vary enough from the documented
approximations to be worth calibrating once you can compare a rendered
photo against the real hardware. Stored as Frame.palette_rgb (NULL =
default, schema migration v4), threaded through render_frame/
render_placeholder/_quantize_and_pack (which now builds the PIL palette
image per call instead of once at import) so both photos and the
unclaimed/unconfigured placeholder screen respect it. "Reset to
defaults" clears back to NULL. Config-save validates exactly 6 #rrggbb
values, rejecting anything else with a 400.
Also: each frame's sidebar entry now shows its last-reported battery
percent (🔋NN%) next to the name, using the frame_dot's existing
recently-seen indicator conventions -- silent when never reported
(mains-only frames, or before the first report), matching how battery
is hidden everywhere else it's not applicable.
Verified against the same live-shaped database as the SMTP work: the
v3->v4 migration, save/reload/reset round trip through the real HTTP
route, an actual rendered image using a custom palette (confirmed via
its packed panel-code bytes), input validation, and the sidebar badge
against real battery data -- plus the standing legacy-device curl suite.
This commit is contained in:
@@ -112,6 +112,26 @@
|
||||
disable. Needs SMTP configured by an admin.</p>
|
||||
<button type="button" class="secondary" id="battery-alert-save">Save</button>
|
||||
</section>
|
||||
|
||||
<details class="card">
|
||||
<summary class="card-title">Advanced configuration</summary>
|
||||
<p class="sub">Color-quantization values used when dithering photos
|
||||
for this panel -- approximations by default, since exact primaries
|
||||
aren't published. Tune them by comparing a rendered photo against
|
||||
the physical panel; different panel units can vary enough to be
|
||||
worth calibrating per frame.</p>
|
||||
<div class="palette-grid">
|
||||
{% set current_hex = palette_to_hex(frame.palette_rgb or default_palette_rgb) %}
|
||||
{% for label in palette_labels %}
|
||||
<label class="palette-swatch">
|
||||
<input type="color" id="palette_{{ loop.index0 }}" value="{{ current_hex[loop.index0] }}">
|
||||
{{ label }}
|
||||
</label>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<button type="button" class="secondary" id="palette-save">Save</button>
|
||||
<button type="button" class="secondary" id="palette-reset">Reset to defaults</button>
|
||||
</details>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -119,6 +139,9 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<script>window.FRAME_API = {{ ("/api/frames/" ~ frame.id) | tojson }};</script>
|
||||
<script>
|
||||
window.FRAME_API = {{ ("/api/frames/" ~ frame.id) | tojson }};
|
||||
window.DEFAULT_PALETTE_HEX = {{ palette_to_hex(default_palette_rgb) | tojson }};
|
||||
</script>
|
||||
<script src="/static/frame_config.js"></script>
|
||||
{% endblock %}
|
||||
|
||||
Reference in New Issue
Block a user