Skip to content

Commit 4e637f7

Browse files
authored
🪿 Update Canadian info 🇨🇦 (#255)
1 parent d3591b9 commit 4e637f7

4 files changed

Lines changed: 124 additions & 60 deletions

File tree

debug.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ const apiCalls = [
3131

3232
let client: BlueLinky;
3333
let vehicle;
34-
const { username, password, pin } = config;
34+
const { username, password, pin, useInfo = false } = config;
3535

3636
const onReadyHandler = <T extends Vehicle>(vehicles: T[]) => {
3737
vehicle = vehicles[0];
@@ -122,34 +122,39 @@ async function performCommand(command) {
122122
const status = await vehicle.status({
123123
refresh: false,
124124
parsed: true,
125+
useInfo,
125126
});
126127
console.log('status : ' + JSON.stringify(status, null, 2));
127128
break;
128129
case 'statusU':
129130
const statusU = await vehicle.status({
130131
refresh: false,
131132
parsed: false,
133+
useInfo,
132134
});
133135
console.log('status : ' + JSON.stringify(statusU, null, 2));
134136
break;
135137
case 'statusR':
136138
const statusR = await vehicle.status({
137139
refresh: true,
138-
parsed: true
140+
parsed: true,
141+
useInfo,
139142
});
140143
console.log('status remote : ' + JSON.stringify(statusR, null, 2));
141144
break;
142145
case 'fullStatus':
143146
const fullStatus = await vehicle.fullStatus({
144147
refresh: false,
145-
parsed: false
148+
parsed: false,
149+
useInfo,
146150
});
147151
console.log('full status cached : ' + JSON.stringify(fullStatus, null, 2));
148152
break;
149153
case 'fullStatusR':
150154
const fullStatusR = await vehicle.fullStatus({
151155
refresh: true,
152-
parsed: false
156+
parsed: false,
157+
useInfo,
153158
});
154159
console.log('full status remote : ' + JSON.stringify(fullStatusR, null, 2));
155160
break;

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/interfaces/common.interfaces.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ export interface VehicleStatus {
6565
steeringwheelHeat: boolean;
6666
sideMirrorHeat: boolean;
6767
rearWindowHeat: boolean;
68-
temperatureSetpoint: number;
68+
temperatureSetpoint: number | string;
6969
temperatureUnit: number;
7070
defrost: boolean;
7171
};
@@ -399,6 +399,7 @@ export interface VehicleOdometer {
399399
export interface VehicleStatusOptions {
400400
refresh: boolean;
401401
parsed: boolean;
402+
useInfo?: boolean;
402403
}
403404

404405
// VEHICLE COMMANDS /////////////////////////////////////////////

src/vehicles/canadian.vehicle.ts

Lines changed: 111 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,38 @@ import {
1818
RawVehicleStatus,
1919
FullVehicleStatus,
2020
EVChargeModeTypes,
21+
VehicleInfo,
22+
VehicleFeatureEntry,
2123
} from '../interfaces/common.interfaces';
22-
2324
import { Vehicle } from './vehicle';
2425
import { celciusToTempCode, parseDate } from '../util';
2526
import { CanadianController } from '../controllers/canadian.controller';
2627
import { ManagedBluelinkyError } from '../tools/common.tools';
2728

29+
30+
export interface CanadianInfo {
31+
vehicle: VehicleInfo;
32+
features: {
33+
seatHeatVent: {
34+
drvSeatHeatOption: number;
35+
astSeatHeatOption: number;
36+
rlSeatHeatOption: number;
37+
rrSeatHeatOption: number;
38+
};
39+
hvacTempType: number;
40+
targetMinSoc: number;
41+
strgWhlHeatingOption: number;
42+
};
43+
featuresModel: {
44+
features: [VehicleFeatureEntry];
45+
};
46+
status: RawVehicleStatus;
47+
}
48+
2849
export default class CanadianVehicle extends Vehicle {
2950
public region = REGIONS.CA;
3051
private timeOffset = -(new Date().getTimezoneOffset() / 60);
52+
private _info: CanadianInfo | null = null;
3153

3254
constructor(public vehicleConfig: VehicleRegisterOptions, public controller: CanadianController) {
3355
super(vehicleConfig, controller);
@@ -48,60 +70,70 @@ export default class CanadianVehicle extends Vehicle {
4870

4971
logger.debug('Begin status request, polling car', statusConfig.refresh);
5072
try {
51-
const endpoint = statusConfig.refresh
52-
? this.controller.environment.endpoints.remoteStatus
53-
: this.controller.environment.endpoints.status;
54-
const response = await this.request(endpoint, {});
55-
const vehicleStatus = response.result?.status;
56-
57-
if (response?.error) {
58-
throw response?.error?.errorDesc;
73+
let vehicleStatus: RawVehicleStatus | null = null;
74+
if (statusConfig.useInfo) {
75+
await this.setInfo(statusConfig.refresh);
76+
if (this._info) {
77+
vehicleStatus = this._info.status;
78+
}
79+
} else {
80+
const endpoint = statusConfig.refresh
81+
? this.controller.environment.endpoints.remoteStatus
82+
: this.controller.environment.endpoints.status;
83+
const response = await this.request(endpoint, {});
84+
vehicleStatus = response.result?.status;
85+
86+
if (response?.error) {
87+
throw response?.error?.errorDesc;
88+
}
5989
}
60-
6190
logger.debug(vehicleStatus);
62-
const parsedStatus: VehicleStatus = {
63-
chassis: {
64-
hoodOpen: vehicleStatus?.hoodOpen,
65-
trunkOpen: vehicleStatus?.trunkOpen,
66-
locked: vehicleStatus?.doorLock,
67-
openDoors: {
68-
frontRight: !!vehicleStatus?.doorOpen?.frontRight,
69-
frontLeft: !!vehicleStatus?.doorOpen?.frontLeft,
70-
backLeft: !!vehicleStatus?.doorOpen?.backLeft,
71-
backRight: !!vehicleStatus?.doorOpen?.backRight,
91+
let parsedStatus: VehicleStatus | null = null;
92+
if (vehicleStatus) {
93+
parsedStatus = {
94+
chassis: {
95+
hoodOpen: vehicleStatus?.hoodOpen,
96+
trunkOpen: vehicleStatus?.trunkOpen,
97+
locked: vehicleStatus?.doorLock,
98+
openDoors: {
99+
frontRight: !!vehicleStatus?.doorOpen?.frontRight,
100+
frontLeft: !!vehicleStatus?.doorOpen?.frontLeft,
101+
backLeft: !!vehicleStatus?.doorOpen?.backLeft,
102+
backRight: !!vehicleStatus?.doorOpen?.backRight,
103+
},
104+
tirePressureWarningLamp: {
105+
rearLeft: !!vehicleStatus?.tirePressureLamp?.tirePressureWarningLampRearLeft,
106+
frontLeft: !!vehicleStatus?.tirePressureLamp?.tirePressureWarningLampFrontLeft,
107+
frontRight: !!vehicleStatus?.tirePressureLamp?.tirePressureWarningLampFrontRight,
108+
rearRight: !!vehicleStatus?.tirePressureLamp?.tirePressureWarningLampRearRight,
109+
all: !!vehicleStatus?.tirePressureLamp?.tirePressureWarningLampAll,
110+
},
72111
},
73-
tirePressureWarningLamp: {
74-
rearLeft: !!vehicleStatus?.tirePressureLamp?.tirePressureWarningLampRearLeft,
75-
frontLeft: !!vehicleStatus?.tirePressureLamp?.tirePressureWarningLampFrontLeft,
76-
frontRight: !!vehicleStatus?.tirePressureLamp?.tirePressureWarningLampFrontRight,
77-
rearRight: !!vehicleStatus?.tirePressureLamp?.tirePressureWarningLampRearRight,
78-
all: !!vehicleStatus?.tirePressureLamp?.tirePressureWarningLampAll,
112+
climate: {
113+
active: vehicleStatus?.airCtrlOn,
114+
steeringwheelHeat: !!vehicleStatus?.steerWheelHeat,
115+
sideMirrorHeat: false,
116+
rearWindowHeat: !!vehicleStatus?.sideBackWindowHeat,
117+
defrost: vehicleStatus?.defrost,
118+
temperatureSetpoint: vehicleStatus?.airTemp?.value,
119+
temperatureUnit: vehicleStatus?.airTemp?.unit,
79120
},
80-
},
81-
climate: {
82-
active: vehicleStatus?.airCtrlOn,
83-
steeringwheelHeat: !!vehicleStatus?.steerWheelHeat,
84-
sideMirrorHeat: false,
85-
rearWindowHeat: !!vehicleStatus?.sideBackWindowHeat,
86-
defrost: vehicleStatus?.defrost,
87-
temperatureSetpoint: vehicleStatus?.airTemp?.value,
88-
temperatureUnit: vehicleStatus?.airTemp?.unit,
89-
},
90121

91-
// TODO: fix props for parsed???
92-
// Seems some of the translation would have to account for EV and ICE
93-
// as they are often in different locations on the response
94-
// example EV status is in lib/__mock__/canadianStatus.json
95-
engine: {
96-
ignition: vehicleStatus?.engine,
97-
accessory: vehicleStatus?.acc,
98-
range: vehicleStatus?.dte?.value,
99-
charging: vehicleStatus?.evStatus?.batteryCharge,
100-
batteryCharge12v: vehicleStatus?.battery?.batSoc,
101-
batteryChargeHV: vehicleStatus?.evStatus?.batteryStatus,
102-
},
103-
lastupdate: vehicleStatus?.time ? parseDate(vehicleStatus?.lastStatusDate) : null,
104-
};
122+
// TODO: fix props for parsed???
123+
// Seems some of the translation would have to account for EV and ICE
124+
// as they are often in different locations on the response
125+
// example EV status is in lib/__mock__/canadianStatus.json
126+
engine: {
127+
ignition: vehicleStatus?.engine,
128+
accessory: vehicleStatus?.acc,
129+
range: vehicleStatus?.dte?.value,
130+
charging: vehicleStatus?.evStatus?.batteryCharge,
131+
batteryCharge12v: vehicleStatus?.battery?.batSoc,
132+
batteryChargeHV: vehicleStatus?.evStatus?.batteryStatus,
133+
},
134+
lastupdate: parseDate(vehicleStatus?.lastStatusDate),
135+
};
136+
}
105137

106138
this._status = statusConfig.parsed ? parsedStatus : vehicleStatus;
107139
return this._status;
@@ -289,8 +321,17 @@ export default class CanadianVehicle extends Vehicle {
289321
}
290322

291323
// TODO: @Seb to take a look at doing this
292-
public odometer(): Promise<VehicleOdometer | null> {
293-
throw new Error('Method not implemented.');
324+
public async odometer(): Promise<VehicleOdometer | null> {
325+
try {
326+
await this.setInfo();
327+
if (this._info) {
328+
return { unit: this._info.vehicle.odometer, value: this._info.vehicle.odometerUnit };
329+
} else {
330+
throw 'error: no info';
331+
}
332+
} catch (err) {
333+
throw 'error: ' + err;
334+
}
294335
}
295336

296337
public async location(): Promise<VehicleLocation> {
@@ -325,7 +366,7 @@ export default class CanadianVehicle extends Vehicle {
325366

326367
// TODO: not sure how to type a dynamic response
327368
/* eslint-disable @typescript-eslint/no-explicit-any */
328-
private async request(endpoint, body: any, headers: any = {}): Promise<any | null> {
369+
private async request(endpoint: string, body: any, headers: any = {}): Promise<any | null> {
329370
logger.debug(`[${endpoint}] ${JSON.stringify(headers)} ${JSON.stringify(body)}`);
330371

331372
// add logic for token refresh to ensure we don't use a stale token
@@ -361,4 +402,21 @@ export default class CanadianVehicle extends Vehicle {
361402
throw 'error: ' + err;
362403
}
363404
}
405+
406+
private async setInfo(refresh = false): Promise<void> {
407+
if (this._info !== null && !refresh) {
408+
return;
409+
}
410+
try {
411+
const preAuth = await this.getPreAuth();
412+
const response = await this.request(
413+
this.controller.environment.endpoints.vehicleInfo,
414+
{},
415+
{ pAuth: preAuth }
416+
);
417+
this._info = response.result as CanadianInfo;
418+
} catch (err) {
419+
throw 'error: ' + err;
420+
}
421+
}
364422
}

0 commit comments

Comments
 (0)