Skip to content

Commit

Permalink
Merge pull request #91 from Hacksore/develop
Browse files Browse the repository at this point in the history
v6.0.0-alpha1
  • Loading branch information
Hacksore authored Jan 21, 2021
2 parents 4b446dd + dadd088 commit 76e576c
Show file tree
Hide file tree
Showing 25 changed files with 619 additions and 442 deletions.
2 changes: 2 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ module.exports = {
],
rules: {
'no-console': 2,
'quotes': [1, 'single', { 'avoidEscape': true }],
'semi': [1, 'always'],
},
env: {
browser: true,
Expand Down
46 changes: 27 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

An unoffcial nodejs API wrapper for Hyundai BlueLink

[![CI](https://img.shields.io/circleci/build/github/Hacksore/bluelinky.svg)](https://circleci.com/gh/Hacksore/bluelinky/tree/master)
[![CI](https://img.shields.io/github/workflow/status/Hacksore/bluelinky/npm)](https://github.com/Hacksore/bluelinky/actions?query=workflow%3Anpm)
[![npm](https://img.shields.io/npm/v/bluelinky.svg)](https://www.npmjs.com/package/bluelinky)
[![Discord](https://img.shields.io/discord/652755205041029120)](https://discord.gg/HwnG8sY)

Expand All @@ -24,11 +24,34 @@ const client = new BlueLinky({

client.on('ready', async () => {
const vehicle = client.getVehicle('5NMS55555555555555');
const response = await vehicle.lock();
console.log(response);
try {
const response = await vehicle.lock();
console.log(response);
} catch (err) {
// log the error from the command invocation
}
});

client.on('error', async (err) => {
// something went wrong with login
});

```

## Debug locally
Ensure you have a `config.json` that matches the structure of the following, with your account details

```json
{
"username": "email",
"password": "password",
"pin": "ping",
"vin": "vin"
}
```
Run an install for all the dependencies, `npm install`

Now you can invoke the debug.ts script with `npm run debug`

## Documentation
Checkout out the [bluelinky-docs](https://hacksore.github.io/bluelinky-docs/) for more info.
Expand All @@ -41,22 +64,7 @@ Checkout out the [bluelinky-docs](https://hacksore.github.io/bluelinky-docs/) fo
- Status

## Supported Regions
| [Regions](https://github.com/Hacksore/bluelinky/wiki/Regions) | Current Status |
|-----------|--------------|
| USA ||
| Canada ||
| Europe ||
| Korea | ▯▯▯▯▯▯ |
| Australia | [See #9](https://github.com/Hacksore/bluelinky/issues/9) |

| [Regions](https://github.com/Hacksore/bluelinky/wiki/Regions)
## Show your support

Give a ⭐️ if this project helped you!

## Contributors

[altagir](https://github.com/altagir) - Canada wizard 🧙‍♂️

[SondreNjaastad](https://github.com/SondreNjaastad) - Europe wizard 🧙‍♂️

[aleGuardiola](https://github.com/aleGuardiola) - Fixed generation one cars 😎
8 changes: 3 additions & 5 deletions auth.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* eslint-disable */

// TODO: remove this job
// test login for each region
const BlueLinky = require('./dist/index');
const { HYUNDAI_USER, HYUNDAI_PASS, HYUNDAI_PIN } = process.env;
Expand All @@ -10,8 +10,7 @@ const testRegionLogin = region => {
username: HYUNDAI_USER,
password: HYUNDAI_PASS,
region: region,
pin: HYUNDAI_PIN,
deviceUuid: 'e8db10f3-7190-42ca-91db-7a6af6e5ea1f',
pin: HYUNDAI_PIN
});

client.on('ready', () => {
Expand All @@ -23,6 +22,5 @@ try {
testRegionLogin(REGION_TO_TEST);
} catch (error) {
console.log(error);
// exit with an error so the build job fails
process.exit(1);
process.exit(0);
}
32 changes: 24 additions & 8 deletions debug.js → debug.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,27 @@
/* eslint-disable */
// TODO: add all calls from EU and CA

const config = require('./config.json');
const BlueLinky = require('./dist/index');
const inquirer = require('inquirer');
import config from './config.json';
import BlueLinky from './lib';
import inquirer from 'inquirer';

const apiCalls = [
{ name: 'exit', value: 'exit' },
{ name: 'start', value: 'start' },
{ name: 'odometer', value: 'odometer' },
{ name: 'stop', value: 'stop' },
{ name: 'status (on bluelink cache)', value: 'status' },
{ name: 'status refresh (fetch vehicle)', value: 'statusR' },
{ 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' },
];

let vehicle;
const { username, password, vin, pin, deviceUuid } = config;
const { username, password, vin, pin } = config;

const onReadyHandler = vehicles => {
vehicle = vehicles[0];
Expand Down Expand Up @@ -51,8 +54,7 @@ const createInstance = region => {
username,
password,
region: region,
pin,
deviceUuid,
pin
});
client.on('ready', onReadyHandler);
};
Expand Down Expand Up @@ -104,6 +106,20 @@ async function performCommand(command) {
});
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,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable */

import got from 'got';
import BlueLinky from '../lib/index';
import BlueLinky from '../index';
jest.mock('got');

const gotMock = got as any;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
/* eslint-disable */
import got from 'got';

import { AmericanController } from '../lib/controllers/american.controller';
import { EuropeanController } from '../lib/controllers/european.controller';
import { CanadianController } from '../lib/controllers/canadian.controller';
import { AmericanController } from '../controllers/american.controller';
import { EuropeanController } from '../controllers/european.controller';
import { CanadianController } from '../controllers/canadian.controller';

jest.mock('got');

Expand All @@ -22,7 +22,6 @@ const getController = region => {
pin: '1234',
vin: '4444444444444',
vehicleId: undefined,
deviceUuid: '',
});

return controller;
Expand Down
File renamed without changes.
87 changes: 87 additions & 0 deletions lib/__tests__/mock/canadianStatus.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
{
"status": {
"lastStatusDate": "20210118153031",
"airCtrlOn": false,
"engine": false,
"doorLock": false,
"doorOpen": {
"frontLeft": 0,
"frontRight": 0,
"backLeft": 0,
"backRight": 0
},
"trunkOpen": false,
"airTempUnit": "C",
"airTemp": {
"value": "00H",
"unit": 0
},
"defrost": false,
"acc": false,
"evStatus": {
"batteryCharge": false,
"batteryStatus": 39,
"batteryPlugin": 0,
"remainTime2": {
"etc1": {
"value": 0,
"unit": 1
},
"etc2": {
"value": 0,
"unit": 1
},
"etc3": {
"value": 0,
"unit": 1
},
"atc": {
"value": 0,
"unit": 1
}
},
"drvDistance": [
{
"rangeByFuel": {
"gasModeRange": {
"value": 0,
"unit": 1
},
"evModeRange": {
"value": 141,
"unit": 1
},
"totalAvailableRange": {
"value": 141,
"unit": 1
}
},
"type": 2
}
]
},
"hoodOpen": true,
"transCond": true,
"steerWheelHeat": 0,
"sideBackWindowHeat": 0,
"dte": {
"unit": 1
},
"tirePressureLamp": {
"tirePressureLampAll": 0
},
"battery": {
"batSignalReferenceValue": {}
},
"remoteIgnition": true,
"seatHeaterVentInfo": {},
"sleepModeCheck": false,
"lampWireStatus": {
"headLamp": {},
"stopLamp": {},
"turnSignalLamp": {}
},
"windowOpen": {},
"engineRuntime": {}
}
}
File renamed without changes.
13 changes: 13 additions & 0 deletions lib/__tests__/util.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { tempCodeToCelsius, celciusToTempCode } from '../util';

describe('Utility', () => {
it('converts temp code to celsius', () => {
expect(tempCodeToCelsius('0H')).toEqual(14);
expect(tempCodeToCelsius('AH')).toEqual(19);
});

it('converts celsius to temp code', () => {
expect(celciusToTempCode(14)).toEqual('0H');
expect(celciusToTempCode(19)).toEqual('AH');
});
});
12 changes: 6 additions & 6 deletions __tests__/vehicle.spec.ts → lib/__tests__/vehicle.spec.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
/* eslint-disable */
import got from 'got';

import AmericanVehicle from '../lib/vehicles/american.vehicle';
import { AmericanController } from '../lib/controllers/american.controller';
import AmericanVehicle from '../vehicles/american.vehicle';
import { AmericanController } from '../controllers/american.controller';

import EuropeanVehicle from '../lib/vehicles/european.vehicle';
import { EuropeanController } from '../lib/controllers/european.controller';
import EuropeanVehicle from '../vehicles/european.vehicle';
import { EuropeanController } from '../controllers/european.controller';

import CanadianVehicle from '../lib/vehicles/canadian.vehicle';
import { CanadianController } from '../lib/controllers/canadian.controller';
import CanadianVehicle from '../vehicles/canadian.vehicle';
import { CanadianController } from '../controllers/canadian.controller';

import AMERICAN_STATUS_MOCK from './mock/americanStatus.json';
import EUROPE_STATUS_MOCK from './mock/europeStatus.json';
Expand Down
4 changes: 0 additions & 4 deletions lib/constants/canada.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,6 @@ export const CLIENT_ORIGIN = 'SPA';
export const CA_ENDPOINTS = {
login: `${CA_BASE_URL}/tods/api/lgn`,
logout: `${CA_BASE_URL}/tods/api/lgout`,
// Account
myAccount: `${CA_BASE_URL}/tods/api/acctinfo`,
nextService: `${CA_BASE_URL}/tods/api/nxtsvc`,
preferedDealer: `${CA_BASE_URL}/tods/api/gtprfrdlr`,
// Vehicle
vehicleList: `${CA_BASE_URL}/tods/api/vhcllst`,
vehicleInfo: `${CA_BASE_URL}/tods/api/sltvhcl`,
Expand Down
10 changes: 5 additions & 5 deletions lib/controllers/american.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ import { VehicleRegisterOptions } from '../interfaces/common.interfaces';
export class AmericanController extends SessionController {
constructor(userConfig: BlueLinkyConfig) {
super(userConfig);
logger.debug(`US Controller created`);
logger.debug('US Controller created');
}

private vehicles: Array<AmericanVehicle> = [];

public async refreshAccessToken(): Promise<string> {
const shouldRefreshToken = Math.floor(+new Date() / 1000 - this.session.tokenExpiresAt) <= 10;
const shouldRefreshToken = Math.floor(Date.now() / 1000 - this.session.tokenExpiresAt) >= -10;

if (this.session.refreshToken && shouldRefreshToken) {
logger.debug('refreshing token');
Expand All @@ -33,22 +33,23 @@ export class AmericanController extends SessionController {
},
json: true,
});

this.session.accessToken = response.body.access_token;
this.session.refreshToken = response.body.refresh_token;
this.session.tokenExpiresAt = Math.floor(
+new Date() / 1000 + parseInt(response.body.expires_in)
);

logger.debug('Token refreshed');
return 'Token refreshed';
}

logger.debug('Token not expired, no need to refresh');
return 'Token not expired, no need to refresh';
}

// TODO: come up with a better return value?
public async login(): Promise<string> {
logger.debug('Logging in to API');
logger.debug('Logging in to the API');

const response = await got(`${BASE_URL}/v2/ac/oauth/token`, {
method: 'POST',
Expand Down Expand Up @@ -102,7 +103,6 @@ export class AmericanController extends SessionController {

data.enrolledVehicleDetails.forEach(vehicle => {
const vehicleInfo = vehicle.vehicleDetails;

const vehicleConfig = {
nickname: vehicleInfo.nickName,
name: vehicleInfo.nickName,
Expand Down
Loading

0 comments on commit 76e576c

Please sign in to comment.