fix(proxy): fix UpSnap wake — use /api/upsnap/wake endpoint
PATCH { status: "on" } no longer works in current UpSnap version.
Switch to GET /api/upsnap/wake/{id} with 10s timeout (WoL packet
is sent immediately, endpoint blocks until device responds).
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -63,31 +63,60 @@ async function upSnapFetch(path: string, options: RequestInit = {}): Promise<Res
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function wakeDevice(): Promise<void> {
|
export async function wakeDevice(): Promise<void> {
|
||||||
const res = await upSnapFetch(
|
// Use the dedicated wake endpoint — it sends a WoL packet.
|
||||||
`/api/collections/devices/records/${config.upsnap.deviceId}`,
|
// This endpoint may block until the device responds or its internal timeout expires,
|
||||||
{ method: 'PATCH', body: JSON.stringify({ status: 'on' }) }
|
// so we abort after 10s — the WoL packet is already sent by then.
|
||||||
|
const authToken = await getToken();
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await fetch(
|
||||||
|
`${config.upsnap.url}/api/upsnap/wake/${config.upsnap.deviceId}`,
|
||||||
|
{
|
||||||
|
method: 'GET',
|
||||||
|
headers: { Authorization: authToken },
|
||||||
|
signal: AbortSignal.timeout(10_000),
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
if (res.ok) return;
|
if (res.status === 401 || res.status === 403) {
|
||||||
|
const newToken = await authenticate();
|
||||||
const body1 = await res.text().catch(() => '');
|
await fetch(
|
||||||
console.error(`[UpSnap] PATCH wake failed (${res.status}): ${body1}`);
|
`${config.upsnap.url}/api/upsnap/wake/${config.upsnap.deviceId}`,
|
||||||
|
{
|
||||||
// Fallback: GET wake endpoint
|
|
||||||
const res2 = await upSnapFetch(`/api/upsnap/wake/${config.upsnap.deviceId}`, {
|
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
});
|
headers: { Authorization: newToken },
|
||||||
if (!res2.ok) {
|
signal: AbortSignal.timeout(10_000),
|
||||||
const body2 = await res2.text().catch(() => '');
|
},
|
||||||
throw new Error(`UpSnap wake failed: ${res2.status} — ${body2}`);
|
).catch(() => {});
|
||||||
|
// WoL packet sent regardless of response
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
const body = await res.text().catch(() => '');
|
||||||
|
throw new Error(`UpSnap wake failed: ${res.status} — ${body}`);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
// AbortError / TimeoutError is expected — the WoL packet was already sent
|
||||||
|
if (err instanceof DOMException && err.name === 'TimeoutError') {
|
||||||
|
console.log('[UpSnap] Wake request timed out (expected — WoL packet was sent)');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (err instanceof DOMException && err.name === 'AbortError') {
|
||||||
|
console.log('[UpSnap] Wake request aborted (expected — WoL packet was sent)');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function shutdownDevice(): Promise<void> {
|
export async function shutdownDevice(): Promise<void> {
|
||||||
const res = await upSnapFetch(`/api/upsnap/shutdown/${config.upsnap.deviceId}`, {
|
const res = await upSnapFetch(`/api/upsnap/shutdown/${config.upsnap.deviceId}`, {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
|
signal: AbortSignal.timeout(10_000),
|
||||||
});
|
});
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
throw new Error(`UpSnap shutdown failed: ${res.status}`);
|
const body = await res.text().catch(() => '');
|
||||||
|
throw new Error(`UpSnap shutdown failed: ${res.status} — ${body}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user