/** * AIS Target API 클라이언트 * SNP-Batch 서버의 AIS 데이터를 HTTP 폴링으로 조회 */ import axios from 'axios'; // dev: Vite 프록시 (/snp-api → 211.208.115.83:8041) // prod: 환경변수로 직접 지정 const BASE_URL = import.meta.env.VITE_API_URL || '/snp-api'; /** * AIS 타겟 검색 (최근 N분 데이터) * @param {number} minutes - 조회 기간 (분) * @returns {Promise} AIS 타겟 데이터 배열 */ export async function searchAisTargets(minutes = 60) { const res = await axios.get(`${BASE_URL}/api/ais-target/search`, { params: { minutes }, timeout: 30000, }); return res.data.data || []; } /** * AIS API 응답 → shipStore feature 객체로 변환 * * API 응답 필드: * mmsi, imo, name, callsign, vesselType, lat, lon, * heading, sog, cog, rot, length, width, draught, * destination, eta, status, messageTimestamp, receivedDate, * source, classType * * @param {Object} aisTarget - API 응답 단건 * @returns {Object} shipStore 호환 feature 객체 */ export function aisTargetToFeature(aisTarget) { const mmsi = String(aisTarget.mmsi || ''); // 백엔드에서 signalKindCode를 직접 제공, 없으면 vesselType 기반 fallback const signalKindCode = aisTarget.signalKindCode || mapVesselTypeToKindCode(aisTarget.vesselType); return { // 고유 식별자 (AIS 신호원 코드 + MMSI) featureId: `000001${mmsi}`, // 기본 식별 정보 targetId: mmsi, originalTargetId: mmsi, signalSourceCode: '000001', // AIS shipName: aisTarget.name || '', shipType: aisTarget.vesselType || '', // 위치 정보 longitude: aisTarget.lon || 0, latitude: aisTarget.lat || 0, // 항해 정보 sog: aisTarget.sog || 0, cog: aisTarget.cog || 0, // 시간 정보 receivedTime: formatTimestamp(aisTarget.messageTimestamp), // 선종 코드 signalKindCode, // 상태 플래그 lost: false, integrate: false, isPriority: true, // 위험물 카테고리 hazardousCategory: '', // 국적 코드 nationalCode: '', // IMO 번호 imo: String(aisTarget.imo || ''), // 흘수 draught: String(aisTarget.draught || ''), // 선박 크기 dimA: '', dimB: '', dimC: '', dimD: '', // AVETDR 신호장비 플래그 ais: '1', vpass: '', enav: '', vtsAis: '', dMfHf: '', vtsRadar: '', // 추가 메타데이터 callsign: aisTarget.callsign || '', heading: aisTarget.heading || 0, destination: aisTarget.destination || '', status: aisTarget.status || '', length: aisTarget.length || 0, width: aisTarget.width || 0, _raw: null, }; } /** * vesselType 문자열 → 선종 코드 매핑 */ function mapVesselTypeToKindCode(vesselType) { if (!vesselType) return '000027'; // 일반 const vt = vesselType.toLowerCase(); if (vt.includes('fishing')) return '000020'; // 어선 if (vt.includes('passenger')) return '000022'; // 여객선 if (vt.includes('cargo')) return '000023'; // 화물선 if (vt.includes('tanker')) return '000024'; // 유조선 if (vt.includes('military') || vt.includes('law enforcement')) return '000025'; // 관공선 if (vt.includes('tug') || vt.includes('pilot') || vt.includes('search')) return '000025'; // 관공선 return '000027'; // 일반 } /** * ISO 타임스탬프 → "YYYYMMDDHHmmss" 형식 변환 */ function formatTimestamp(isoString) { if (!isoString) return ''; try { const d = new Date(isoString); const pad = (n) => String(n).padStart(2, '0'); return `${d.getFullYear()}${pad(d.getMonth() + 1)}${pad(d.getDate())}${pad(d.getHours())}${pad(d.getMinutes())}${pad(d.getSeconds())}`; } catch { return ''; } }