/** * Клиент Traccar REST API. * Настройка через env: TRACCAR_API_URL, TRACCAR_USER, TRACCAR_PASSWORD. * Если переменные не заданы — все методы тихо no-op с логом, * чтобы GPS-модуль работал и без Traccar (например, только PWA-трекинг). */ const TRACCAR_API_URL = process.env.TRACCAR_API_URL; const TRACCAR_USER = process.env.TRACCAR_USER; const TRACCAR_PASSWORD = process.env.TRACCAR_PASSWORD; function isConfigured(): boolean { return Boolean(TRACCAR_API_URL && TRACCAR_USER && TRACCAR_PASSWORD); } function authHeaders(): Record { const basic = Buffer.from(`${TRACCAR_USER}:${TRACCAR_PASSWORD}`).toString("base64"); return { Authorization: `Basic ${basic}`, "Content-Type": "application/json", }; } interface TraccarDevice { id: number; uniqueId: string; name: string; } /** Найти устройство по uniqueId; возвращает null, если не найдено */ async function findDevice(uniqueId: string): Promise { const url = `${TRACCAR_API_URL}/api/devices?uniqueId=${encodeURIComponent(uniqueId)}`; const res = await fetch(url, { headers: authHeaders() }); if (!res.ok) { throw new Error(`Traccar GET /api/devices: HTTP ${res.status}`); } const devices = (await res.json()) as TraccarDevice[]; return devices.find((d) => d.uniqueId === uniqueId) ?? null; } /** * Создаёт устройство в Traccar, если его ещё нет. * Возвращает id устройства или null при ошибке/отсутствии конфигурации. */ export async function ensureDevice(uniqueId: string, name: string): Promise { if (!isConfigured()) { console.log("[GPS] Traccar не настроен (TRACCAR_API_URL/USER/PASSWORD), ensureDevice пропущен"); return null; } try { const existing = await findDevice(uniqueId); if (existing) return existing.id; const res = await fetch(`${TRACCAR_API_URL}/api/devices`, { method: "POST", headers: authHeaders(), body: JSON.stringify({ uniqueId, name }), }); if (!res.ok) { const text = await res.text().catch(() => ""); throw new Error(`Traccar POST /api/devices: HTTP ${res.status} ${text}`); } const device = (await res.json()) as TraccarDevice; console.log(`[GPS] Traccar: создано устройство '${name}' (${uniqueId}), id=${device.id}`); return device.id; } catch (err) { console.error("[GPS] Traccar ensureDevice error:", err); return null; } } /** Удаляет устройство из Traccar по uniqueId (если существует) */ export async function deleteDevice(uniqueId: string): Promise { if (!isConfigured()) { console.log("[GPS] Traccar не настроен, deleteDevice пропущен"); return; } try { const existing = await findDevice(uniqueId); if (!existing) return; const res = await fetch(`${TRACCAR_API_URL}/api/devices/${existing.id}`, { method: "DELETE", headers: authHeaders(), }); if (!res.ok && res.status !== 404) { throw new Error(`Traccar DELETE /api/devices/${existing.id}: HTTP ${res.status}`); } console.log(`[GPS] Traccar: удалено устройство ${uniqueId}`); } catch (err) { console.error("[GPS] Traccar deleteDevice error:", err); } }