UNPKG

@drfrost/bods-js

Version:

JavaScript client for the UK's Bus Open Data Service (BODS) API

197 lines (196 loc) 6.34 kB
/** * Client for interacting with the BODS Automatic Vehicle Location (AVL) API * * The AVL API provides real-time bus location data in two formats: * - SIRI-VM (XML format) * - GTFS-RT (Protocol Buffers format) * * Data is updated every 10 seconds. */ export class AVLClient { constructor(httpClient) { this.httpClient = httpClient; } /** * Get real-time vehicle locations in SIRI-VM format (XML) * * @param params - Search parameters to filter vehicle data * @returns Promise resolving to SIRI-VM XML data * * @example * ```typescript * // Get all vehicles from specific operators * const vehicles = await client.avl.getSIRIVM({ * operatorRef: ['SCGH', 'SCLI'] * }); * * // Get vehicles in a specific area (Liverpool) * const areaVehicles = await client.avl.getSIRIVM({ * boundingBox: [-2.930, 53.374, -3.085, 53.453] * }); * * // Get vehicles on a specific line * const lineVehicles = await client.avl.getSIRIVM({ * lineRef: '85A' * }); * ``` */ async getSIRIVM(params = {}) { const response = await this.httpClient.get('/api/v1/datafeed', params); return { xmlData: response.data }; } /** * Get a specific SIRI-VM datafeed by ID * * @param datafeedId - The unique datafeed identifier * @returns Promise resolving to SIRI-VM XML data * * @example * ```typescript * const datafeed = await client.avl.getSIRIVMById(123); * ``` */ async getSIRIVMById(datafeedId) { const response = await this.httpClient.get(`/api/v1/datafeed/${datafeedId}/`); return { xmlData: response.data }; } /** * Get real-time vehicle locations in GTFS-RT format (Protocol Buffers) * * @param params - Search parameters to filter vehicle data * @returns Promise resolving to GTFS-RT protobuf data * * @example * ```typescript * // Get all vehicles in GTFS-RT format * const vehicles = await client.avl.getGTFSRT({ * boundingBox: [-2.930, 53.374, -3.085, 53.453] * }); * * // Get vehicles for a specific route * const routeVehicles = await client.avl.getGTFSRT({ * routeId: 'route_123' * }); * ``` */ async getGTFSRT(params = {}) { const response = await this.httpClient.get('/api/v1/gtfsrtdatafeed/', params); return { protobufData: response.data }; } /** * Get vehicles by operator in SIRI-VM format * * @param operatorRef - Operator reference(s) (often National Operator Code) * @param additionalParams - Additional search parameters * @returns Promise resolving to SIRI-VM XML data * * @example * ```typescript * const stagecoachVehicles = await client.avl.getByOperator(['SCMN', 'SCGH']); * ``` */ async getByOperator(operatorRef, additionalParams = {}) { return this.getSIRIVM({ ...additionalParams, operatorRef: Array.isArray(operatorRef) ? operatorRef : [operatorRef] }); } /** * Get vehicles by line reference in SIRI-VM format * * @param lineRef - Line reference (route number/identifier) * @param additionalParams - Additional search parameters * @returns Promise resolving to SIRI-VM XML data * * @example * ```typescript * const line85AVehicles = await client.avl.getByLine('85A'); * ``` */ async getByLine(lineRef, additionalParams = {}) { return this.getSIRIVM({ ...additionalParams, lineRef }); } /** * Get vehicles by vehicle reference in SIRI-VM format * * @param vehicleRef - Vehicle reference/identifier * @param additionalParams - Additional search parameters * @returns Promise resolving to SIRI-VM XML data * * @example * ```typescript * const specificVehicle = await client.avl.getByVehicle('BUSC-001'); * ``` */ async getByVehicle(vehicleRef, additionalParams = {}) { return this.getSIRIVM({ ...additionalParams, vehicleRef }); } /** * Get vehicles in a specific geographic area * * @param boundingBox - Geographic bounding box [minLng, minLat, maxLng, maxLat] * @param format - Data format ('siri-vm' or 'gtfs-rt') * @param additionalParams - Additional search parameters * @returns Promise resolving to location data in specified format * * @example * ```typescript * // Liverpool area in SIRI-VM format * const liverpoolVehicles = await client.avl.getByArea( * [-2.930, 53.374, -3.085, 53.453], * 'siri-vm' * ); * * // Manchester area in GTFS-RT format * const manchesterVehicles = await client.avl.getByArea( * [-2.3, 53.4, -2.2, 53.5], * 'gtfs-rt' * ); * ``` */ async getByArea(boundingBox, format = 'siri-vm', additionalParams = {}) { if (format === 'gtfs-rt') { return this.getGTFSRT({ ...additionalParams, boundingBox }); } return this.getSIRIVM({ ...additionalParams, boundingBox }); } /** * Helper method to create bounding box from center point and radius * * @param centerLat - Center latitude * @param centerLng - Center longitude * @param radiusKm - Radius in kilometers * @returns Bounding box coordinates * * @example * ```typescript * const bbox = client.avl.createBoundingBox(53.4808, -2.2426, 5); // Manchester, 5km radius * const nearbyVehicles = await client.avl.getByArea(bbox); * ``` */ createBoundingBox(centerLat, centerLng, radiusKm) { // Approximate degrees per kilometer const latDegPerKm = 1 / 111; const lngDegPerKm = 1 / (111 * Math.cos(centerLat * Math.PI / 180)); const latOffset = radiusKm * latDegPerKm; const lngOffset = radiusKm * lngDegPerKm; return [ centerLng - lngOffset, // minLng centerLat - latOffset, // minLat centerLng + lngOffset, // maxLng centerLat + latOffset // maxLat ]; } }