2026-09-19 03:54:34 +03:00
|
|
|
|
// lib/common/services/network.service.js
|
|
|
|
|
|
//
|
2026-09-19 15:54:26 +03:00
|
|
|
|
// Проверка подключения через эндпоинты бэкенда:
|
2026-09-19 03:54:34 +03:00
|
|
|
|
//
|
2026-09-19 15:54:26 +03:00
|
|
|
|
// - /api/is_server — публичный сервер unitprint.ru.
|
|
|
|
|
|
// Отвечает {"is_server":true} → интернет есть, скан доступен;
|
|
|
|
|
|
// - local.unitprint.ru/api/is_local — локальный сервер печати.
|
|
|
|
|
|
// Отвечает {"is_local":true} → устройство в Wi-Fi принтера (UnitPrintLocal),
|
|
|
|
|
|
// печать доступна.
|
|
|
|
|
|
//
|
|
|
|
|
|
// Сайт всегда отдаётся с unitprint.ru, поэтому проверка локалки ходит
|
|
|
|
|
|
// на отдельный хост local.unitprint.ru: вне локальной сети принтера
|
|
|
|
|
|
// он просто недоступен.
|
2026-09-19 03:54:34 +03:00
|
|
|
|
//
|
|
|
|
|
|
// Скан работает только через интернет, печать — только через локальную сеть.
|
|
|
|
|
|
|
2026-09-19 15:54:26 +03:00
|
|
|
|
export const LOCAL_HOST = 'local.unitprint.ru';
|
2026-09-19 03:54:34 +03:00
|
|
|
|
export const LOCAL_WIFI_NAME = 'UnitPrintLocal';
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2026-09-19 15:54:26 +03:00
|
|
|
|
* GET с таймаутом, читаем JSON.
|
|
|
|
|
|
* @returns {Promise<any|null>} null — если хост недоступен или ошибка.
|
|
|
|
|
|
*/
|
|
|
|
|
|
async function getJson(url, timeoutMs = 4000) {
|
|
|
|
|
|
if (typeof fetch === 'undefined') return null;
|
|
|
|
|
|
const controller = new AbortController();
|
|
|
|
|
|
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
|
|
|
|
try {
|
|
|
|
|
|
const res = await fetch(url, {
|
|
|
|
|
|
method: 'GET',
|
|
|
|
|
|
cache: 'no-store',
|
|
|
|
|
|
signal: controller.signal,
|
|
|
|
|
|
});
|
|
|
|
|
|
if (!res.ok) return null;
|
|
|
|
|
|
return await res.json();
|
|
|
|
|
|
} catch {
|
|
|
|
|
|
return null;
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
clearTimeout(timer);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Доступность хоста в режиме 'no-cors': CORS не мешает, важен сам факт ответа.
|
2026-09-19 03:54:34 +03:00
|
|
|
|
*/
|
|
|
|
|
|
async function canReach(url, timeoutMs = 4000) {
|
|
|
|
|
|
if (typeof fetch === 'undefined') return false;
|
|
|
|
|
|
const controller = new AbortController();
|
|
|
|
|
|
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
|
|
|
|
try {
|
|
|
|
|
|
await fetch(url, {
|
|
|
|
|
|
method: 'GET',
|
|
|
|
|
|
mode: 'no-cors',
|
|
|
|
|
|
cache: 'no-store',
|
|
|
|
|
|
signal: controller.signal,
|
|
|
|
|
|
});
|
|
|
|
|
|
return true;
|
|
|
|
|
|
} catch {
|
|
|
|
|
|
return false;
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
clearTimeout(timer);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-09-19 15:54:26 +03:00
|
|
|
|
/**
|
|
|
|
|
|
* Устройство в локальной сети принтера:
|
|
|
|
|
|
* local.unitprint.ru/api/is_local отвечает {"is_local":true}.
|
|
|
|
|
|
*/
|
|
|
|
|
|
export async function isLocalNetwork() {
|
2026-09-19 03:54:34 +03:00
|
|
|
|
const ts = Date.now();
|
2026-09-19 15:54:26 +03:00
|
|
|
|
const httpsUrl = `https://${LOCAL_HOST}/api/is_local?ping=${ts}`;
|
|
|
|
|
|
const httpUrl = `http://${LOCAL_HOST}/api/is_local?ping=${ts}`;
|
|
|
|
|
|
|
|
|
|
|
|
const data = (await getJson(httpsUrl, 3000)) ?? (await getJson(httpUrl, 3000));
|
|
|
|
|
|
if (data) return data.is_local === true;
|
2026-09-19 03:54:34 +03:00
|
|
|
|
|
2026-09-19 15:54:26 +03:00
|
|
|
|
// JSON не читается (CORS / самоподписанный сертификат) —fallback:
|
|
|
|
|
|
// сам факт ответа local.unitprint.ru означает, что мы в локалке.
|
|
|
|
|
|
return canReach(httpsUrl, 3000);
|
2026-09-19 03:54:34 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2026-09-19 15:54:26 +03:00
|
|
|
|
* Есть интернет: публичный сервер отвечает на /api/is_server.
|
2026-09-19 03:54:34 +03:00
|
|
|
|
*/
|
2026-09-19 15:54:26 +03:00
|
|
|
|
export async function isServerReachable() {
|
|
|
|
|
|
const data = await getJson(`/api/is_server?ping=${Date.now()}`, 5000);
|
|
|
|
|
|
return data?.is_server === true;
|
2026-09-19 03:54:34 +03:00
|
|
|
|
}
|