Add configurable baud rate for Adalight with dynamic FPS hint
Baud rate is now a first-class device field, passed through the full stack: Device model → API schemas → routes → ProcessorManager → AdalightClient. The frontend shows a baud rate dropdown (115200–2M) for Adalight devices in both Add Device and Settings modals, with a live "Max FPS ≈ N" hint computed from LED count and baud rate. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -763,11 +763,27 @@ async function showSettings(deviceId) {
|
||||
ledCountGroup.style.display = 'none';
|
||||
}
|
||||
|
||||
// Show baud rate field for adalight devices
|
||||
const baudRateGroup = document.getElementById('settings-baud-rate-group');
|
||||
if (isAdalight) {
|
||||
baudRateGroup.style.display = '';
|
||||
const baudSelect = document.getElementById('settings-baud-rate');
|
||||
if (device.baud_rate) {
|
||||
baudSelect.value = String(device.baud_rate);
|
||||
} else {
|
||||
baudSelect.value = '115200';
|
||||
}
|
||||
updateSettingsBaudFpsHint();
|
||||
} else {
|
||||
baudRateGroup.style.display = 'none';
|
||||
}
|
||||
|
||||
// Snapshot initial values for dirty checking
|
||||
settingsInitialValues = {
|
||||
name: device.name,
|
||||
url: device.url,
|
||||
led_count: String(device.led_count || ''),
|
||||
baud_rate: String(device.baud_rate || '115200'),
|
||||
device_type: device.device_type,
|
||||
capabilities: caps,
|
||||
state_check_interval: '30',
|
||||
@@ -838,12 +854,16 @@ async function saveDeviceSettings() {
|
||||
}
|
||||
|
||||
try {
|
||||
// Update device info (name, url, optionally led_count)
|
||||
// Update device info (name, url, optionally led_count, baud_rate)
|
||||
const body = { name, url };
|
||||
const ledCountInput = document.getElementById('settings-led-count');
|
||||
if ((settingsInitialValues.capabilities || []).includes('manual_led_count') && ledCountInput.value) {
|
||||
body.led_count = parseInt(ledCountInput.value, 10);
|
||||
}
|
||||
if (settingsInitialValues.device_type === 'adalight') {
|
||||
const baudVal = document.getElementById('settings-baud-rate').value;
|
||||
if (baudVal) body.baud_rate = parseInt(baudVal, 10);
|
||||
}
|
||||
const deviceResponse = await fetch(`${API_BASE}/devices/${deviceId}`, {
|
||||
method: 'PUT',
|
||||
headers: getHeaders(),
|
||||
@@ -930,12 +950,15 @@ function onDeviceTypeChanged() {
|
||||
const ledCountGroup = document.getElementById('device-led-count-group');
|
||||
const discoverySection = document.getElementById('discovery-section');
|
||||
|
||||
const baudRateGroup = document.getElementById('device-baud-rate-group');
|
||||
|
||||
if (deviceType === 'adalight') {
|
||||
urlGroup.style.display = 'none';
|
||||
urlInput.removeAttribute('required');
|
||||
serialGroup.style.display = '';
|
||||
serialSelect.setAttribute('required', '');
|
||||
ledCountGroup.style.display = '';
|
||||
baudRateGroup.style.display = '';
|
||||
// Hide discovery list — serial port dropdown replaces it
|
||||
if (discoverySection) discoverySection.style.display = 'none';
|
||||
// Populate from cache or show placeholder (lazy-load on focus)
|
||||
@@ -949,12 +972,14 @@ function onDeviceTypeChanged() {
|
||||
opt.disabled = true;
|
||||
serialSelect.appendChild(opt);
|
||||
}
|
||||
updateBaudFpsHint();
|
||||
} else {
|
||||
urlGroup.style.display = '';
|
||||
urlInput.setAttribute('required', '');
|
||||
serialGroup.style.display = 'none';
|
||||
serialSelect.removeAttribute('required');
|
||||
ledCountGroup.style.display = 'none';
|
||||
baudRateGroup.style.display = 'none';
|
||||
// Show cached results or trigger scan for WLED
|
||||
if (deviceType in _discoveryCache) {
|
||||
_renderDiscoveryList();
|
||||
@@ -964,6 +989,36 @@ function onDeviceTypeChanged() {
|
||||
}
|
||||
}
|
||||
|
||||
function _computeMaxFps(baudRate, ledCount) {
|
||||
if (!baudRate || !ledCount || ledCount < 1) return null;
|
||||
const bitsPerFrame = (ledCount * 3 + 6) * 10;
|
||||
return Math.floor(baudRate / bitsPerFrame);
|
||||
}
|
||||
|
||||
function _renderFpsHint(hintEl, baudRate, ledCount) {
|
||||
const fps = _computeMaxFps(baudRate, ledCount);
|
||||
if (fps !== null) {
|
||||
hintEl.textContent = `Max FPS ≈ ${fps}`;
|
||||
hintEl.style.display = '';
|
||||
} else {
|
||||
hintEl.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
function updateBaudFpsHint() {
|
||||
const hintEl = document.getElementById('baud-fps-hint');
|
||||
const baudRate = parseInt(document.getElementById('device-baud-rate').value, 10);
|
||||
const ledCount = parseInt(document.getElementById('device-led-count').value, 10);
|
||||
_renderFpsHint(hintEl, baudRate, ledCount);
|
||||
}
|
||||
|
||||
function updateSettingsBaudFpsHint() {
|
||||
const hintEl = document.getElementById('settings-baud-fps-hint');
|
||||
const baudRate = parseInt(document.getElementById('settings-baud-rate').value, 10);
|
||||
const ledCount = parseInt(document.getElementById('settings-led-count').value, 10);
|
||||
_renderFpsHint(hintEl, baudRate, ledCount);
|
||||
}
|
||||
|
||||
function _renderDiscoveryList() {
|
||||
const selectedType = document.getElementById('device-type').value;
|
||||
const devices = _discoveryCache[selectedType];
|
||||
@@ -1226,6 +1281,10 @@ async function handleAddDevice(event) {
|
||||
if (ledCountInput && ledCountInput.value) {
|
||||
body.led_count = parseInt(ledCountInput.value, 10);
|
||||
}
|
||||
const baudRateSelect = document.getElementById('device-baud-rate');
|
||||
if (deviceType === 'adalight' && baudRateSelect && baudRateSelect.value) {
|
||||
body.baud_rate = parseInt(baudRateSelect.value, 10);
|
||||
}
|
||||
const lastTemplateId = localStorage.getItem('lastCaptureTemplateId');
|
||||
if (lastTemplateId) {
|
||||
body.capture_template_id = lastTemplateId;
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
🔑 <span data-i18n="auth.login">Login</span>
|
||||
</button>
|
||||
<button id="logout-btn" class="btn btn-danger" onclick="logout()" style="display: none; padding: 6px 16px; font-size: 0.85rem; margin-left: 10px;">
|
||||
🚪 <span data-i18n="auth.logout">Logout</span>
|
||||
🚪
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
@@ -260,7 +260,25 @@
|
||||
<button type="button" class="hint-toggle" onclick="toggleHint(this)" title="?">?</button>
|
||||
</div>
|
||||
<small class="input-hint" style="display:none" data-i18n="device.led_count_manual.hint">Number of LEDs on the strip (must match your Arduino sketch)</small>
|
||||
<input type="number" id="settings-led-count" min="1" max="10000">
|
||||
<input type="number" id="settings-led-count" min="1" max="10000" oninput="updateSettingsBaudFpsHint()">
|
||||
</div>
|
||||
<div class="form-group" id="settings-baud-rate-group" style="display: none;">
|
||||
<div class="label-row">
|
||||
<label for="settings-baud-rate" data-i18n="device.baud_rate">Baud Rate:</label>
|
||||
<button type="button" class="hint-toggle" onclick="toggleHint(this)" title="?">?</button>
|
||||
</div>
|
||||
<small class="input-hint" style="display:none" data-i18n="device.baud_rate.hint">Serial communication speed. Higher = more FPS but requires matching Arduino sketch.</small>
|
||||
<select id="settings-baud-rate" onchange="updateSettingsBaudFpsHint()">
|
||||
<option value="115200">115200</option>
|
||||
<option value="230400">230400</option>
|
||||
<option value="460800">460800</option>
|
||||
<option value="500000">500000</option>
|
||||
<option value="921600">921600</option>
|
||||
<option value="1000000">1000000</option>
|
||||
<option value="1500000">1500000</option>
|
||||
<option value="2000000">2000000</option>
|
||||
</select>
|
||||
<small id="settings-baud-fps-hint" class="fps-hint" style="display:none"></small>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
@@ -641,7 +659,25 @@
|
||||
<button type="button" class="hint-toggle" onclick="toggleHint(this)" title="?">?</button>
|
||||
</div>
|
||||
<small class="input-hint" style="display:none" data-i18n="device.led_count_manual.hint">Number of LEDs on the strip (must match your Arduino sketch)</small>
|
||||
<input type="number" id="device-led-count" min="1" max="10000" placeholder="60">
|
||||
<input type="number" id="device-led-count" min="1" max="10000" placeholder="60" oninput="updateBaudFpsHint()">
|
||||
</div>
|
||||
<div class="form-group" id="device-baud-rate-group" style="display: none;">
|
||||
<div class="label-row">
|
||||
<label for="device-baud-rate" data-i18n="device.baud_rate">Baud Rate:</label>
|
||||
<button type="button" class="hint-toggle" onclick="toggleHint(this)" title="?">?</button>
|
||||
</div>
|
||||
<small class="input-hint" style="display:none" data-i18n="device.baud_rate.hint">Serial communication speed. Higher = more FPS but requires matching Arduino sketch.</small>
|
||||
<select id="device-baud-rate" onchange="updateBaudFpsHint()">
|
||||
<option value="115200">115200</option>
|
||||
<option value="230400">230400</option>
|
||||
<option value="460800">460800</option>
|
||||
<option value="500000">500000</option>
|
||||
<option value="921600">921600</option>
|
||||
<option value="1000000">1000000</option>
|
||||
<option value="1500000">1500000</option>
|
||||
<option value="2000000">2000000</option>
|
||||
</select>
|
||||
<small id="baud-fps-hint" class="fps-hint" style="display:none"></small>
|
||||
</div>
|
||||
<div id="add-device-error" class="error-message" style="display: none;"></div>
|
||||
</form>
|
||||
|
||||
@@ -112,6 +112,8 @@
|
||||
"device.serial_port.hint": "Select the COM port of the Adalight device",
|
||||
"device.serial_port.none": "No serial ports found",
|
||||
"device.led_count_manual.hint": "Number of LEDs on the strip (must match your Arduino sketch)",
|
||||
"device.baud_rate": "Baud Rate:",
|
||||
"device.baud_rate.hint": "Serial communication speed. Higher = more FPS but requires matching Arduino sketch.",
|
||||
"device.url.hint": "IP address or hostname of the device (e.g. http://192.168.1.100)",
|
||||
"device.name": "Device Name:",
|
||||
"device.name.placeholder": "Living Room TV",
|
||||
|
||||
@@ -112,6 +112,8 @@
|
||||
"device.serial_port.hint": "Выберите COM порт устройства Adalight",
|
||||
"device.serial_port.none": "Серийные порты не найдены",
|
||||
"device.led_count_manual.hint": "Количество светодиодов на ленте (должно совпадать с вашим скетчем Arduino)",
|
||||
"device.baud_rate": "Скорость порта:",
|
||||
"device.baud_rate.hint": "Скорость серийного соединения. Выше = больше FPS, но требует соответствия скетчу Arduino.",
|
||||
"device.url.hint": "IP адрес или имя хоста устройства (напр. http://192.168.1.100)",
|
||||
"device.name": "Имя Устройства:",
|
||||
"device.name.placeholder": "ТВ в Гостиной",
|
||||
|
||||
@@ -1160,6 +1160,13 @@ input:-webkit-autofill:focus {
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
.fps-hint {
|
||||
display: block;
|
||||
margin-top: 4px;
|
||||
font-size: 0.82rem;
|
||||
color: var(--info-color, #2196F3);
|
||||
}
|
||||
|
||||
.slider-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
Reference in New Issue
Block a user