import { Injectable, Logger } from '@nestjs/common'; import { AdsbExchange, Bearing, ExtendedAircraft } from './types'; import { DDPoint, Haversine, UnitOfDistance } from 'haversine-ts'; import axios from 'axios'; import { ConfigService } from '@nestjs/config'; const ValidRadii = [1, 5, 10, 25, 50, 100, 250] as const; export type ValidRadius = (typeof ValidRadii)[number]; @Injectable() export class AdsbExchangeService { private readonly logger: Logger = new Logger(AdsbExchangeService.name); constructor(private readonly configService: ConfigService) {} isValidRadius(radius: number): radius is ValidRadius { return ValidRadii.includes(radius as ValidRadius); } bearingToAircraft( aircraft: AdsbExchange.Aircraft, location: AdsbExchange.Location, ): Bearing { const locationPoint = new DDPoint(location.lat, location.long); const aircraftPoint = new DDPoint(aircraft.lat, aircraft.lon); const haversine = new Haversine(UnitOfDistance.Mile); const bearing = haversine.getBearing(locationPoint, aircraftPoint); return { bearing: bearing.start, distance: haversine.getDistance(locationPoint, aircraftPoint), }; } async adsbExchangeAircraftWithinRadius( radius: ValidRadius, location: AdsbExchange.Location, ): Promise { this.logger.verbose( `Requesting aircraft within ${radius} nautical miles of ${location.lat}, ${location.long}`, ); const options = { method: 'GET', url: `https://adsbexchange-com1.p.rapidapi.com/v2/lat/${location.lat}/lon/${location.long}/dist/${radius}/`, headers: { 'x-rapidapi-key': this.configService.get('rapidApiKey'), 'x-rapidapi-host': 'adsbexchange-com1.p.rapidapi.com', }, }; try { const response = await axios.request(options); return response.data.ac; } catch (error) { this.logger.error(error); return []; } } extendAircraft( aircraft: AdsbExchange.Aircraft[], location: AdsbExchange.Location, ): ExtendedAircraft[] { return aircraft.map((a) => ({ ...a, bearing: this.bearingToAircraft(a, location), })); } liteAircraft = (aircraft: ExtendedAircraft[]) => aircraft.map((a) => ({ flight: a.flight, registration: a.r, type: a.t, altitude: a.alt_baro, speed: a.gs, track: a.track, bearing: a.bearing, })); }