fix(ui): enforce save semantics for default and preset chunks
This commit is contained in:
Submodule led-driver updated: 044dd815dc...fb53f900fb
@@ -171,9 +171,13 @@ async def send_presets(request, session):
|
|||||||
if not sender:
|
if not sender:
|
||||||
return json.dumps({"error": "Transport not configured"}), 503, {'Content-Type': 'application/json'}
|
return json.dumps({"error": "Transport not configured"}), 503, {'Content-Type': 'application/json'}
|
||||||
|
|
||||||
async def send_chunk(chunk_presets):
|
async def send_chunk(chunk_presets, is_last):
|
||||||
# Include save flag so the led-driver can persist when desired.
|
# Save/default should only be sent with the final presets chunk.
|
||||||
msg = build_message(presets=chunk_presets, save=save_flag, default=default_id)
|
msg = build_message(
|
||||||
|
presets=chunk_presets,
|
||||||
|
save=save_flag and is_last,
|
||||||
|
default=default_id if is_last else None,
|
||||||
|
)
|
||||||
await sender.send(msg, addr=destination_mac)
|
await sender.send(msg, addr=destination_mac)
|
||||||
|
|
||||||
MAX_BYTES = 240
|
MAX_BYTES = 240
|
||||||
@@ -195,7 +199,7 @@ async def send_presets(request, session):
|
|||||||
last_msg = test_msg
|
last_msg = test_msg
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
await send_chunk(batch)
|
await send_chunk(batch, False)
|
||||||
except Exception:
|
except Exception:
|
||||||
return json.dumps({"error": "Send failed"}), 503, {'Content-Type': 'application/json'}
|
return json.dumps({"error": "Send failed"}), 503, {'Content-Type': 'application/json'}
|
||||||
await asyncio.sleep(send_delay_s)
|
await asyncio.sleep(send_delay_s)
|
||||||
@@ -205,7 +209,7 @@ async def send_presets(request, session):
|
|||||||
|
|
||||||
if batch:
|
if batch:
|
||||||
try:
|
try:
|
||||||
await send_chunk(batch)
|
await send_chunk(batch, True)
|
||||||
except Exception:
|
except Exception:
|
||||||
return json.dumps({"error": "Send failed"}), 503, {'Content-Type': 'application/json'}
|
return json.dumps({"error": "Send failed"}), 503, {'Content-Type': 'application/json'}
|
||||||
await asyncio.sleep(send_delay_s)
|
await asyncio.sleep(send_delay_s)
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ const sendEspnowMessage = (obj) => {
|
|||||||
|
|
||||||
// Send a select message for a preset to all device names in the current tab.
|
// Send a select message for a preset to all device names in the current tab.
|
||||||
// Uses the preset ID as the select key.
|
// Uses the preset ID as the select key.
|
||||||
const sendSelectForCurrentTabDevices = (presetId, sectionEl, saveToDevice = true) => {
|
const sendSelectForCurrentTabDevices = (presetId, sectionEl) => {
|
||||||
const section = sectionEl || document.querySelector('.presets-section[data-tab-id]');
|
const section = sectionEl || document.querySelector('.presets-section[data-tab-id]');
|
||||||
if (!section || !presetId) {
|
if (!section || !presetId) {
|
||||||
return;
|
return;
|
||||||
@@ -155,9 +155,6 @@ const sendSelectForCurrentTabDevices = (presetId, sectionEl, saveToDevice = true
|
|||||||
v: '1',
|
v: '1',
|
||||||
select,
|
select,
|
||||||
};
|
};
|
||||||
if (saveToDevice) {
|
|
||||||
message.save = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
sendEspnowMessage(message);
|
sendEspnowMessage(message);
|
||||||
};
|
};
|
||||||
@@ -1325,9 +1322,8 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
|
|
||||||
// Build ESPNow messages for a single preset.
|
// Build ESPNow messages for a single preset.
|
||||||
// Send order:
|
// Send order:
|
||||||
// 1) preset payload (without save)
|
// 1) preset payload (optionally with save)
|
||||||
// 2) optional select for device names
|
// 2) optional select for device names (never with save)
|
||||||
// 3) optional save command
|
|
||||||
// saveToDevice defaults to true.
|
// saveToDevice defaults to true.
|
||||||
const sendPresetViaEspNow = async (presetId, preset, deviceNames, saveToDevice = true, setDefault = false) => {
|
const sendPresetViaEspNow = async (presetId, preset, deviceNames, saveToDevice = true, setDefault = false) => {
|
||||||
try {
|
try {
|
||||||
@@ -1394,11 +1390,13 @@ const sendDefaultPreset = (presetId, deviceNames) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Default should only set startup preset, not trigger live selection.
|
// Default should only set startup preset, not trigger live selection.
|
||||||
|
// Save is attached to default messages.
|
||||||
// When device names are provided, scope the default update to those devices.
|
// When device names are provided, scope the default update to those devices.
|
||||||
const targets = Array.isArray(deviceNames)
|
const targets = Array.isArray(deviceNames)
|
||||||
? deviceNames.map((n) => (n || '').trim()).filter((n) => n.length > 0)
|
? deviceNames.map((n) => (n || '').trim()).filter((n) => n.length > 0)
|
||||||
: [];
|
: [];
|
||||||
const message = { v: '1', default: presetId };
|
const message = { v: '1', default: presetId };
|
||||||
|
message.save = true;
|
||||||
if (targets.length > 0) {
|
if (targets.length > 0) {
|
||||||
message.targets = targets;
|
message.targets = targets;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -354,7 +354,7 @@ async function loadTabContent(tabId) {
|
|||||||
brightnessSendTimeout = setTimeout(() => {
|
brightnessSendTimeout = setTimeout(() => {
|
||||||
if (typeof window.sendEspnowRaw === 'function') {
|
if (typeof window.sendEspnowRaw === 'function') {
|
||||||
try {
|
try {
|
||||||
window.sendEspnowRaw({ v: '1', b: val });
|
window.sendEspnowRaw({ v: '1', b: val, save: true });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Failed to send brightness via ESPNow:', err);
|
console.error('Failed to send brightness via ESPNow:', err);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user