Add frame-change detection, keepalive, current FPS, and compact metrics UI
Skip redundant processing/DDP sends when screen is static using object identity comparison. Add configurable standby interval to periodically resend last frame keeping WLED in live mode. Track frames skipped, keepalive count, and current FPS (rolling 1-second send count). Always use DDP regardless of LED count. Compact metrics grid with label-value rows and remove Skipped from UI display. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -3821,6 +3821,8 @@ async function showTargetEditor(targetId = null) {
|
||||
document.getElementById('target-editor-interpolation').value = target.settings?.interpolation_mode ?? 'average';
|
||||
document.getElementById('target-editor-smoothing').value = target.settings?.smoothing ?? 0.3;
|
||||
document.getElementById('target-editor-smoothing-value').textContent = target.settings?.smoothing ?? 0.3;
|
||||
document.getElementById('target-editor-standby-interval').value = target.settings?.standby_interval ?? 1.0;
|
||||
document.getElementById('target-editor-standby-interval-value').textContent = target.settings?.standby_interval ?? 1.0;
|
||||
document.getElementById('target-editor-title').textContent = t('targets.edit');
|
||||
} else {
|
||||
// Creating new target
|
||||
@@ -3834,6 +3836,8 @@ async function showTargetEditor(targetId = null) {
|
||||
document.getElementById('target-editor-interpolation').value = 'average';
|
||||
document.getElementById('target-editor-smoothing').value = 0.3;
|
||||
document.getElementById('target-editor-smoothing-value').textContent = '0.3';
|
||||
document.getElementById('target-editor-standby-interval').value = 1.0;
|
||||
document.getElementById('target-editor-standby-interval-value').textContent = '1.0';
|
||||
document.getElementById('target-editor-title').textContent = t('targets.add');
|
||||
}
|
||||
|
||||
@@ -3845,6 +3849,7 @@ async function showTargetEditor(targetId = null) {
|
||||
border_width: document.getElementById('target-editor-border-width').value,
|
||||
interpolation: document.getElementById('target-editor-interpolation').value,
|
||||
smoothing: document.getElementById('target-editor-smoothing').value,
|
||||
standby_interval: document.getElementById('target-editor-standby-interval').value,
|
||||
};
|
||||
|
||||
const modal = document.getElementById('target-editor-modal');
|
||||
@@ -3868,7 +3873,8 @@ function isTargetEditorDirty() {
|
||||
document.getElementById('target-editor-fps').value !== targetEditorInitialValues.fps ||
|
||||
document.getElementById('target-editor-border-width').value !== targetEditorInitialValues.border_width ||
|
||||
document.getElementById('target-editor-interpolation').value !== targetEditorInitialValues.interpolation ||
|
||||
document.getElementById('target-editor-smoothing').value !== targetEditorInitialValues.smoothing
|
||||
document.getElementById('target-editor-smoothing').value !== targetEditorInitialValues.smoothing ||
|
||||
document.getElementById('target-editor-standby-interval').value !== targetEditorInitialValues.standby_interval
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3896,6 +3902,7 @@ async function saveTargetEditor() {
|
||||
const borderWidth = parseInt(document.getElementById('target-editor-border-width').value) || 10;
|
||||
const interpolation = document.getElementById('target-editor-interpolation').value;
|
||||
const smoothing = parseFloat(document.getElementById('target-editor-smoothing').value);
|
||||
const standbyInterval = parseFloat(document.getElementById('target-editor-standby-interval').value);
|
||||
const errorEl = document.getElementById('target-editor-error');
|
||||
|
||||
if (!name) {
|
||||
@@ -3913,6 +3920,7 @@ async function saveTargetEditor() {
|
||||
border_width: borderWidth,
|
||||
interpolation_mode: interpolation,
|
||||
smoothing: smoothing,
|
||||
standby_interval: standbyInterval,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -4175,24 +4183,32 @@ function createTargetCard(target, deviceMap, sourceMap) {
|
||||
${isProcessing ? `
|
||||
<div class="metrics-grid">
|
||||
<div class="metric">
|
||||
<div class="metric-value">${state.fps_actual?.toFixed(1) || '0.0'}</div>
|
||||
<div class="metric-label">${t('device.metrics.actual_fps')}</div>
|
||||
<div class="metric-value">${state.fps_actual?.toFixed(1) || '0.0'}</div>
|
||||
</div>
|
||||
<div class="metric">
|
||||
<div class="metric-label">${t('device.metrics.current_fps')}</div>
|
||||
<div class="metric-value">${state.fps_current ?? '-'}</div>
|
||||
</div>
|
||||
<div class="metric">
|
||||
<div class="metric-value">${state.fps_target || 0}</div>
|
||||
<div class="metric-label">${t('device.metrics.target_fps')}</div>
|
||||
<div class="metric-value">${state.fps_target || 0}</div>
|
||||
</div>
|
||||
<div class="metric">
|
||||
<div class="metric-value">${state.fps_potential?.toFixed(0) || '-'}</div>
|
||||
<div class="metric-label">${t('device.metrics.potential_fps')}</div>
|
||||
<div class="metric-value">${state.fps_potential?.toFixed(0) || '-'}</div>
|
||||
</div>
|
||||
<div class="metric">
|
||||
<div class="metric-value">${metrics.frames_processed || 0}</div>
|
||||
<div class="metric-label">${t('device.metrics.frames')}</div>
|
||||
<div class="metric-value">${metrics.frames_processed || 0}</div>
|
||||
</div>
|
||||
<div class="metric">
|
||||
<div class="metric-label">${t('device.metrics.keepalive')}</div>
|
||||
<div class="metric-value">${state.frames_keepalive ?? '-'}</div>
|
||||
</div>
|
||||
<div class="metric">
|
||||
<div class="metric-value">${metrics.errors_count || 0}</div>
|
||||
<div class="metric-label">${t('device.metrics.errors')}</div>
|
||||
<div class="metric-value">${metrics.errors_count || 0}</div>
|
||||
</div>
|
||||
</div>
|
||||
` : ''}
|
||||
|
||||
Reference in New Issue
Block a user