UNPKG

bluelinky2

Version:

An unofficial nodejs API wrapper for Hyundai bluelink

140 lines (112 loc) 4.07 kB
import { AmericanBlueLinkyConfig, AmericanController } from './controllers/american.controller'; import { EuropeanController, EuropeBlueLinkyConfig } from './controllers/european.controller'; import { CanadianBlueLinkyConfig, CanadianController } from './controllers/canadian.controller'; import { EventEmitter } from 'events'; import logger from './logger'; import { Session } from './interfaces/common.interfaces'; import { REGIONS } from './constants'; import AmericanVehicle from './vehicles/american.vehicle'; import EuropeanVehicle from './vehicles/european.vehicle'; import CanadianVehicle from './vehicles/canadian.vehicle'; import { SessionController } from './controllers/controller'; import { Vehicle } from './vehicles/vehicle'; type BluelinkyConfigRegions = AmericanBlueLinkyConfig|CanadianBlueLinkyConfig|EuropeBlueLinkyConfig; const DEFAULT_CONFIG = { username: '', password: '', region: REGIONS.US, brand: 'hyundai', autoLogin: true, pin: '1234', vin: '', vehicleId: undefined, }; class BlueLinky< T extends BluelinkyConfigRegions = AmericanBlueLinkyConfig, REGION = T['region'], VEHICLE_TYPE extends Vehicle = (REGION extends REGIONS.US ? AmericanVehicle : REGION extends REGIONS.CA ? CanadianVehicle : EuropeanVehicle) > extends EventEmitter { private controller: SessionController; private vehicles: Array<VEHICLE_TYPE> = []; private config: T; constructor(config: T) { super(); // merge configs this.config = { ...DEFAULT_CONFIG, ...config, }; switch (config.region) { case REGIONS.EU: this.controller = new EuropeanController(this.config as EuropeBlueLinkyConfig); break; case REGIONS.US: this.controller = new AmericanController(this.config as AmericanBlueLinkyConfig); break; case REGIONS.CA: this.controller = new CanadianController(this.config as CanadianBlueLinkyConfig); break; default: throw new Error('Your region is not supported yet.'); } if (config.autoLogin === undefined) { this.config.autoLogin = true; } this.onInit(); } on(event: 'ready', fnc: (vehicles: VEHICLE_TYPE[]) => void): this; // eslint-disable-next-line @typescript-eslint/no-explicit-any on(event: 'error', fnc: (error: any) => void): this; // eslint-disable-next-line @typescript-eslint/no-explicit-any on(event: string|symbol, listener: (...args: any[]) => void): this { return super.on(event, listener); } private onInit(): void { if (this.config.autoLogin) { logger.debug('Bluelinky is logging in automatically, to disable use autoLogin: false'); this.login(); } } public async login(): Promise<string> { try { const response = await this.controller.login(); // get all cars from the controller this.vehicles = await this.getVehicles(); logger.debug(`Found ${this.vehicles.length} on the account`); this.emit('ready', this.vehicles); return response; } catch (error) { this.emit('error', error); return error; } } async getVehicles(): Promise<VEHICLE_TYPE[]> { return (await this.controller.getVehicles() as unknown[]) as VEHICLE_TYPE[] || []; } public getVehicle(input: string): VEHICLE_TYPE | undefined { try { const foundCar = this.vehicles.find(car => { return car.vin() === input || car.id() === input; }); if (!foundCar && this.vehicles.length > 0) { throw new Error(`Could not find vehicle with id: ${input}`); } return foundCar; } catch (err) { throw new Error(`Vehicle not found: ${input}!`); } } public async refreshAccessToken(): Promise<string> { return this.controller.refreshAccessToken(); } public async logout(): Promise<string> { return this.controller.logout(); } public getSession(): Session | null { return this.controller.session; } public get cachedVehicles(): VEHICLE_TYPE[] { return this.vehicles ?? []; } } export default BlueLinky;