bluelinky2
Version:
An unofficial nodejs API wrapper for Hyundai bluelink
251 lines (240 loc) • 7.88 kB
text/typescript
/* eslint-disable */
// TODO: add all calls from EU and CA
import config from './config.json';
import BlueLinky from './src';
import inquirer from 'inquirer';
import { Vehicle } from './src/vehicles/vehicle';
const apiCalls = [
{ name: 'exit', value: 'exit' },
{ name: 'start', value: 'start' },
{ name: 'vehicles', value: 'vehicles' },
{ name: 'odometer', value: 'odometer' },
{ name: 'stop', value: 'stop' },
{ name: 'status (on server cache)', value: 'status' },
{ name: 'status (on server cache) unparsed', value: 'statusU' },
{ name: 'status refresh (fetch from vehicle)', value: 'statusR' },
{ name: 'full raw status (on server cache)', value: 'fullStatus' },
{ name: 'full raw status refresh (fetch from vehicle)', value: 'fullStatusR' },
{ name: 'lock', value: 'lock' },
{ name: 'unlock', value: 'unlock' },
{ name: 'locate', value: 'locate' },
{ name: '[EU] monthly report', value: 'monthlyReport' },
{ name: '[EU] trip informations', value: 'tripInfo' },
{ name: '[EU] drive informations', value: 'drvInfo' },
{ name: '[EV] get charge targets', value: 'getChargeTargets' },
{ name: '[EV] set charge targets', value: 'setChargeTargets' },
{ name: '[EV] start charging', value: 'startCharge' },
{ name: '[EV] stop charging', value: 'stopCharge' },
];
let client: BlueLinky;
let vehicle;
const { username, password, pin } = config;
const onReadyHandler = <T extends Vehicle>(vehicles: T[]) => {
vehicle = vehicles[0];
askForCommandInput();
};
const askForRegionInput = () => {
inquirer
.prompt([
{
type: 'list',
name: 'region',
message: 'What Region are you in?',
choices: ['US', 'EU', 'CA'],
},
{
type: 'list',
name: 'brand',
message: 'Which brand are you using?',
choices: ['hyundai', 'kia'],
}
])
.then(answers => {
if (answers.command == 'exit') {
return;
} else {
console.log(answers)
console.log('Logging in...');
createInstance(answers.region, answers.brand);
}
});
};
const createInstance = (region, brand) => {
// global abuse :)
client = new BlueLinky({
username,
password,
region,
brand,
pin
});
client.on('ready', onReadyHandler);
};
function askForCommandInput() {
console.log('');
inquirer
.prompt([
{
type: 'list',
name: 'command',
message: 'What you wanna do?',
choices: apiCalls,
},
])
.then(answers => {
if (answers.command == 'exit') {
return;
} else {
performCommand(answers.command);
}
});
}
async function performCommand(command) {
try {
switch (command) {
case 'exit':
return;
case 'locate':
const locate = await vehicle.location();
console.log('locate : ' + JSON.stringify(locate, null, 2));
break;
case 'odometer':
const odometer = await vehicle.odometer();
console.log('odometer', JSON.stringify(odometer, null, 2));
break;
case 'vehicles':
const vehicles = await client.getVehicles();
const response = vehicles.map(v => {
const { name, vin, nickname, regDate } = v.vehicleConfig;
return { name, vin, nickname, regDate };
});
console.log('vehicles', JSON.stringify(response, null, 2));
break;
case 'status':
const status = await vehicle.status({
refresh: false,
parsed: true,
});
console.log('status : ' + JSON.stringify(status, null, 2));
break;
case 'statusU':
const statusU = await vehicle.status({
refresh: false,
parsed: false,
});
console.log('status : ' + JSON.stringify(statusU, null, 2));
break;
case 'statusR':
const statusR = await vehicle.status({
refresh: true,
parsed: true
});
console.log('status remote : ' + JSON.stringify(statusR, null, 2));
break;
case 'fullStatus':
const fullStatus = await vehicle.fullStatus({
refresh: false,
parsed: false
});
console.log('full status cached : ' + JSON.stringify(fullStatus, null, 2));
break;
case 'fullStatusR':
const fullStatusR = await vehicle.fullStatus({
refresh: true,
parsed: false
});
console.log('full status remote : ' + JSON.stringify(fullStatusR, null, 2));
break;
case 'start':
const startRes = await vehicle.start({
airCtrl: false,
igniOnDuration: 10,
airTempvalue: 70,
defrost: false,
heating1: false,
});
console.log('start : ' + JSON.stringify(startRes, null, 2));
break;
case 'stop':
const stopRes = await vehicle.stop();
console.log('stop : ' + JSON.stringify(stopRes, null, 2));
break;
case 'lock':
const lockRes = await vehicle.lock();
console.log('lock : ' + JSON.stringify(lockRes, null, 2));
break;
case 'unlock':
const unlockRes = await vehicle.unlock();
console.log('unlock : ' + JSON.stringify(unlockRes, null, 2));
break;
case 'monthlyReport':
const report = await vehicle.monthlyReport();
console.log('monthyReport : ' + JSON.stringify(report, null, 2));
break;
case 'drvInfo':
const info = await vehicle.driveHistory();
console.log('drvInfo : ');
console.dir(info,{ depth: null });
break;
case 'tripInfo':
const currentYear = new Date().getFullYear();
const { year, month, day } = await inquirer
.prompt([
{
type: 'list',
name: 'year',
message: 'Which year?',
choices: new Array(currentYear - 2015).fill(0).map((_, i) => currentYear - i),
},
{
type: 'list',
name: 'month',
message: 'Which month?',
choices: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
},
{
type: 'list',
name: 'day',
message: 'Which day (0 to ignore the day)?',
choices: new Array(32).fill(0).map((_, i) => i),
}
]);
const trips = await vehicle.tripInfo({ year, month, day: day === 0 ? undefined : day });
console.log('trips : ' + JSON.stringify(trips, null, 2));
break;
case 'getChargeTargets':
const targets = await vehicle.getChargeTargets();
console.log('targets : ' + JSON.stringify(targets, null, 2));
break;
case 'startCharge':
await vehicle.startCharge();
break;
case 'stopCharge':
await vehicle.stopCharge();
break;
case 'setChargeTargets':
const { fast, slow } = await inquirer
.prompt([
{
type: 'list',
name: 'fast',
message: 'What fast charge limit do you which to set?',
choices: [50, 60, 70, 80, 90, 100],
},
{
type: 'list',
name: 'slow',
message: 'What slow charge limit do you which to set?',
choices: [50, 60, 70, 80, 90, 100],
}
]);
await vehicle.setChargeTargets({ fast, slow });
console.log('targets : OK');
break;
}
askForCommandInput();
} catch (err) {
console.log(err);
}
}
askForRegionInput();