import { Injectable, Logger } from "@nestjs/common"; import { GpsDeviceRepository, GpsPositionRepository } from "./gps.repository"; import { GpsDevice } from "./entities/gps-device.entity"; import { Gt06Gps, Gt06Status } from "./gt06/gt06.codec"; /** * Write path for GT06 ingestion: upserts device state and appends position * history. Mirrors the ingestion half of @edr/freight-api's GpsTrackingService * (the REST/query half stays in freight-api). Auto-registers unknown IMEIs on * first contact. */ @Injectable() export class GpsIngestService { private readonly logger = new Logger(GpsIngestService.name); constructor( private readonly devices: GpsDeviceRepository, private readonly positions: GpsPositionRepository, ) {} /** Find the device for an IMEI, auto-registering it on first contact. */ private async ensureDevice(imei: string): Promise { const existing = await this.devices.findByImei(imei); if (existing) return existing; this.logger.log(`Auto-registering new GPS tracker ${imei}`); return this.devices.create({ imei, status: "REGISTERED", lastSeenAt: new Date() }); } async handleLogin(imei: string): Promise { const device = await this.ensureDevice(imei); await this.devices.update(device.id, { lastSeenAt: new Date(), status: "ONLINE" }); } async handleHeartbeat(imei: string, status: Gt06Status): Promise { const device = await this.ensureDevice(imei); await this.devices.update(device.id, { lastSeenAt: new Date(), status: "ONLINE", voltageLevel: status.voltageLevel, gsmLevel: status.gsmLevel, }); } async handleFix(imei: string, gps: Gt06Gps, alarm = 0, status?: Gt06Status): Promise { const device = await this.ensureDevice(imei); const now = new Date(); await this.devices.update(device.id, { lastSeenAt: now, status: "ONLINE", lastLat: gps.latitude, lastLng: gps.longitude, lastSpeed: gps.speed, lastCourse: gps.course, lastFixAt: new Date(gps.time), ...(status ? { voltageLevel: status.voltageLevel, gsmLevel: status.gsmLevel } : {}), }); await this.positions.create({ deviceId: device.id, imei, vehicleId: device.vehicleId ?? null, lat: gps.latitude, lng: gps.longitude, speed: gps.speed, course: gps.course, satellites: gps.satellites, positioned: gps.positioned, gpsTime: new Date(gps.time), alarm, }); } }