feat(espnow): broadcast delivery with group-filtered routing
Send presets and select on broadcast with groups; unicast only for per-device settings. V1 select as [preset_id, step?]. Sequence steps use beat counts; manual presets get select each beat, auto only on step change. Bridge downlink router, Pi envelope delivery, and tests. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -98,12 +98,17 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
: [];
|
||||
};
|
||||
|
||||
const postDriverSequence = async (sequence, targetMacs, delayS = 0.05) => {
|
||||
const body = {
|
||||
sequence,
|
||||
targets: Array.isArray(targetMacs) && targetMacs.length ? [...new Set(targetMacs)] : undefined,
|
||||
delay_s: delayS,
|
||||
};
|
||||
const postDriverSequence = async (sequence, targetMacs, delayS = 0.05, pushOptions = {}) => {
|
||||
if (typeof window.postDriverSequence === 'function') {
|
||||
return window.postDriverSequence(sequence, targetMacs, delayS, pushOptions);
|
||||
}
|
||||
const body = { sequence, delay_s: delayS };
|
||||
if (pushOptions && pushOptions.unicast === true) {
|
||||
body.unicast = true;
|
||||
if (Array.isArray(targetMacs) && targetMacs.length) {
|
||||
body.targets = [...new Set(targetMacs)];
|
||||
}
|
||||
}
|
||||
const res = await fetch('/presets/push', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
|
||||
@@ -586,26 +591,28 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
return;
|
||||
}
|
||||
|
||||
const select = {};
|
||||
deviceNames.forEach((name) => {
|
||||
if (name) {
|
||||
select[name] = zonePresetIds.slice();
|
||||
}
|
||||
});
|
||||
const targetMacs =
|
||||
typeof window.tabsManager !== 'undefined' &&
|
||||
typeof window.tabsManager.resolveTabDeviceMacs === 'function'
|
||||
? await window.tabsManager.resolveTabDeviceMacs(deviceNames)
|
||||
: [];
|
||||
const groupIds =
|
||||
typeof window.zonesManager !== 'undefined' &&
|
||||
typeof window.zonesManager.effectiveGroupIdsForZonePreset === 'function'
|
||||
? window.zonesManager.effectiveGroupIdsForZonePreset(zoneData)
|
||||
: Array.isArray(zoneData.group_ids)
|
||||
? zoneData.group_ids.map((g) => String(g).trim()).filter((g) => g.length > 0)
|
||||
: [];
|
||||
|
||||
const sequence = [
|
||||
{ v: '1', clear_presets: true, save: true },
|
||||
{ v: '1', presets: wirePresets, save: true },
|
||||
];
|
||||
if (Object.keys(select).length) {
|
||||
sequence.push({ v: '1', select });
|
||||
if (groupIds.length) {
|
||||
sequence[0].groups = groupIds;
|
||||
sequence[1].groups = groupIds;
|
||||
}
|
||||
await postDriverSequence(sequence, targetMacs, 0.05);
|
||||
if (deviceNames.length > 0 && zonePresetIds.length > 0) {
|
||||
const sel = { v: '1', select: zonePresetIds.slice() };
|
||||
if (groupIds.length) sel.groups = groupIds;
|
||||
sequence.push(sel);
|
||||
}
|
||||
await postDriverSequence(sequence, [], 0.05, { groupIds });
|
||||
} catch (error) {
|
||||
console.error('Send all patterns failed:', error);
|
||||
alert('Failed to send all patterns.');
|
||||
|
||||
Reference in New Issue
Block a user