iobroker.renault 0.0.21 → 0.0.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +42 -13
- package/admin/i18n/de/translations.json +14 -0
- package/admin/i18n/en/translations.json +14 -0
- package/admin/i18n/es/translations.json +14 -0
- package/admin/i18n/fr/translations.json +14 -0
- package/admin/i18n/it/translations.json +14 -0
- package/admin/i18n/nl/translations.json +14 -0
- package/admin/i18n/pl/translations.json +14 -0
- package/admin/i18n/pt/translations.json +14 -0
- package/admin/i18n/ru/translations.json +14 -0
- package/admin/i18n/uk/translations.json +14 -0
- package/admin/i18n/zh-cn/translations.json +14 -0
- package/admin/jsonConfig.json +99 -0
- package/io-package.json +97 -29
- package/main.js +235 -206
- package/package.json +28 -23
- package/admin/index_m.html +0 -105
- package/admin/style.css +0 -32
- package/admin/words.js +0 -65
- package/lib/json2iob.js +0 -254
- package/lib/tools.js +0 -99
package/main.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
'use strict';
|
|
2
2
|
|
|
3
3
|
/*
|
|
4
4
|
* Created with @iobroker/create-adapter v2.0.1
|
|
@@ -6,10 +6,10 @@
|
|
|
6
6
|
|
|
7
7
|
// The adapter-core module gives you access to the core ioBroker functions
|
|
8
8
|
// you need to create an adapter
|
|
9
|
-
const utils = require(
|
|
10
|
-
const axios = require(
|
|
11
|
-
const qs = require(
|
|
12
|
-
const Json2iob = require(
|
|
9
|
+
const utils = require('@iobroker/adapter-core');
|
|
10
|
+
const axios = require('axios').default;
|
|
11
|
+
const qs = require('qs');
|
|
12
|
+
const Json2iob = require('json2iob');
|
|
13
13
|
|
|
14
14
|
class Renault extends utils.Adapter {
|
|
15
15
|
/**
|
|
@@ -18,16 +18,27 @@ class Renault extends utils.Adapter {
|
|
|
18
18
|
constructor(options) {
|
|
19
19
|
super({
|
|
20
20
|
...options,
|
|
21
|
-
name:
|
|
21
|
+
name: 'renault',
|
|
22
22
|
});
|
|
23
|
-
this.on(
|
|
24
|
-
this.on(
|
|
25
|
-
this.on(
|
|
23
|
+
this.on('ready', this.onReady.bind(this));
|
|
24
|
+
this.on('stateChange', this.onStateChange.bind(this));
|
|
25
|
+
this.on('unload', this.onUnload.bind(this));
|
|
26
26
|
this.deviceArray = [];
|
|
27
27
|
this.json2iob = new Json2iob(this);
|
|
28
28
|
this.ignoreState = {};
|
|
29
29
|
this.firstUpdate = true;
|
|
30
30
|
this.requestClient = axios.create();
|
|
31
|
+
this.userAgent = 'okhttp/5.3.0';
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** APK rI2.smali (WiredHeaderAppVersionInterceptor): build={brand}-android-{version};trId={uuid} on wired Kamereon host */
|
|
35
|
+
buildTraceId() {
|
|
36
|
+
const uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
|
|
37
|
+
const r = (Math.random() * 16) | 0;
|
|
38
|
+
const v = c === 'x' ? r : (r & 0x3) | 0x8;
|
|
39
|
+
return v.toString(16);
|
|
40
|
+
});
|
|
41
|
+
return 'build=renault-android-6.11.2;trId=' + uuid;
|
|
31
42
|
}
|
|
32
43
|
|
|
33
44
|
/**
|
|
@@ -35,23 +46,23 @@ class Renault extends utils.Adapter {
|
|
|
35
46
|
*/
|
|
36
47
|
async onReady() {
|
|
37
48
|
// Reset the connection indicator during startup
|
|
38
|
-
this.setState(
|
|
49
|
+
this.setState('info.connection', false, true);
|
|
39
50
|
if (this.config.interval < 0.5) {
|
|
40
|
-
this.log.info(
|
|
51
|
+
this.log.info('Set interval to minimum 0.5');
|
|
41
52
|
this.config.interval = 0.5;
|
|
42
53
|
}
|
|
43
54
|
this.updateInterval = null;
|
|
44
55
|
this.reLoginTimeout = null;
|
|
45
56
|
this.refreshTokenTimeout = null;
|
|
46
|
-
this.country = this.config.country ||
|
|
57
|
+
this.country = this.config.country || 'de';
|
|
47
58
|
this.session = {};
|
|
48
59
|
//DE API Key
|
|
49
|
-
this.apiKey =
|
|
50
|
-
this.apiKeyUpdate =
|
|
60
|
+
this.apiKey = '3_VgdkgtIRH3AdHvJm-cjV2ug2EFE0lxt0IJzMC4MFqZjFpn_GYFXVdNZ19L7wZX0N';
|
|
61
|
+
this.apiKeyUpdate = 'YjkKtHmGfaceeuExUDKGxrLZGGvtVS0J';
|
|
51
62
|
try {
|
|
52
63
|
await this.requestClient({
|
|
53
|
-
method:
|
|
54
|
-
url:
|
|
64
|
+
method: 'get',
|
|
65
|
+
url: 'https://raw.githubusercontent.com/hacf-fr/renault-api/main/src/renault_api/const.py',
|
|
55
66
|
})
|
|
56
67
|
|
|
57
68
|
.then((res) => {
|
|
@@ -71,16 +82,19 @@ class Renault extends utils.Adapter {
|
|
|
71
82
|
this.apiKeyUpdate = this.config.apiKeyUpdate;
|
|
72
83
|
}
|
|
73
84
|
|
|
74
|
-
this.subscribeStates(
|
|
85
|
+
this.subscribeStates('*');
|
|
75
86
|
|
|
76
87
|
await this.login();
|
|
77
88
|
|
|
78
89
|
if (this.session.id_token && this.session_data && this.account) {
|
|
79
90
|
await this.getDeviceList();
|
|
80
91
|
await this.updateDevices();
|
|
81
|
-
this.updateInterval = setInterval(
|
|
82
|
-
|
|
83
|
-
|
|
92
|
+
this.updateInterval = setInterval(
|
|
93
|
+
async () => {
|
|
94
|
+
await this.updateDevices();
|
|
95
|
+
},
|
|
96
|
+
this.config.interval * 60 * 1000,
|
|
97
|
+
);
|
|
84
98
|
this.refreshTokenInterval = setInterval(() => {
|
|
85
99
|
this.refreshToken();
|
|
86
100
|
}, 3500 * 1000);
|
|
@@ -88,25 +102,29 @@ class Renault extends utils.Adapter {
|
|
|
88
102
|
}
|
|
89
103
|
async login() {
|
|
90
104
|
this.session_data = await this.requestClient({
|
|
91
|
-
method:
|
|
92
|
-
url:
|
|
105
|
+
method: 'post',
|
|
106
|
+
url: 'https://accounts.eu1.gigya.com/accounts.login',
|
|
93
107
|
headers: {
|
|
94
|
-
|
|
95
|
-
Accept:
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
108
|
+
'User-Agent': this.userAgent,
|
|
109
|
+
Accept: '*/*',
|
|
110
|
+
'Accept-Language': 'de-de',
|
|
111
|
+
'Cache-Control': 'no-cache',
|
|
112
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
99
113
|
},
|
|
100
114
|
data: qs.stringify({
|
|
101
115
|
apikey: this.apiKey,
|
|
102
|
-
format:
|
|
103
|
-
httpStatusCodes:
|
|
116
|
+
format: 'json',
|
|
117
|
+
httpStatusCodes: 'false',
|
|
104
118
|
loginID: this.config.username,
|
|
105
119
|
password: this.config.password,
|
|
106
120
|
}),
|
|
107
121
|
})
|
|
108
122
|
.then((res) => {
|
|
109
123
|
this.log.debug(JSON.stringify(res.data));
|
|
124
|
+
if (res.data.errorMessage) {
|
|
125
|
+
this.log.error(JSON.stringify(res.data));
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
110
128
|
return res.data.sessionInfo;
|
|
111
129
|
})
|
|
112
130
|
.catch((error) => {
|
|
@@ -116,32 +134,32 @@ class Renault extends utils.Adapter {
|
|
|
116
134
|
}
|
|
117
135
|
});
|
|
118
136
|
if (!this.session_data) {
|
|
119
|
-
this.log.error(
|
|
137
|
+
this.log.error('No session found for this account. Please login in the app. Maybe a new password is needed.');
|
|
120
138
|
return;
|
|
121
139
|
}
|
|
122
140
|
await this.requestClient({
|
|
123
|
-
method:
|
|
124
|
-
url:
|
|
141
|
+
method: 'post',
|
|
142
|
+
url: 'https://accounts.eu1.gigya.com/accounts.getJWT',
|
|
125
143
|
headers: {
|
|
126
|
-
|
|
127
|
-
Accept:
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
144
|
+
'User-Agent': this.userAgent,
|
|
145
|
+
Accept: '*/*',
|
|
146
|
+
'Accept-Language': 'de-de',
|
|
147
|
+
'Cache-Control': 'no-cache',
|
|
148
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
131
149
|
},
|
|
132
150
|
data: qs.stringify({
|
|
133
|
-
format:
|
|
151
|
+
format: 'json',
|
|
134
152
|
login_token: this.session_data.cookieValue,
|
|
135
|
-
sdk:
|
|
136
|
-
fields:
|
|
153
|
+
sdk: 'js_latest',
|
|
154
|
+
fields: 'data.personId,data.gigyaDataCenter',
|
|
137
155
|
apikey: this.apiKey,
|
|
138
|
-
expiration:
|
|
156
|
+
expiration: '3600',
|
|
139
157
|
}),
|
|
140
158
|
})
|
|
141
159
|
.then((res) => {
|
|
142
160
|
this.log.debug(JSON.stringify(res.data));
|
|
143
161
|
this.session = res.data;
|
|
144
|
-
this.setState(
|
|
162
|
+
this.setState('info.connection', true, true);
|
|
145
163
|
})
|
|
146
164
|
.catch((error) => {
|
|
147
165
|
this.log.error(error);
|
|
@@ -150,59 +168,60 @@ class Renault extends utils.Adapter {
|
|
|
150
168
|
}
|
|
151
169
|
});
|
|
152
170
|
await this.requestClient({
|
|
153
|
-
method:
|
|
154
|
-
url:
|
|
171
|
+
method: 'post',
|
|
172
|
+
url: 'https://apis.renault.com/myr/api/v1/connection?&country=DE&product=MYRENAULT&locale=de-DE&displayAccounts=MYRENAULT',
|
|
155
173
|
headers: {
|
|
156
|
-
|
|
157
|
-
Accept:
|
|
158
|
-
|
|
174
|
+
'Content-Type': 'application/json',
|
|
175
|
+
Accept: '*/*',
|
|
176
|
+
'User-Agent': this.userAgent,
|
|
159
177
|
apiKey: this.apiKeyUpdate,
|
|
160
|
-
|
|
161
|
-
|
|
178
|
+
'Accept-Language': 'de-de',
|
|
179
|
+
'x-gigya-id_token': this.session.id_token,
|
|
162
180
|
},
|
|
163
181
|
})
|
|
164
182
|
.then((res) => {
|
|
165
183
|
this.log.debug(JSON.stringify(res.data));
|
|
166
184
|
|
|
167
185
|
const filteredAccounts = res.data.currentUser.accounts.filter(function (el) {
|
|
168
|
-
return (el.accountType ===
|
|
186
|
+
return (el.accountType === 'MYRENAULT' || el.accountType === 'MYDACIA') && el.accountStatus === 'ACTIVE';
|
|
169
187
|
});
|
|
170
188
|
if (filteredAccounts.length === 0) {
|
|
171
|
-
this.log.error(
|
|
172
|
-
this.log.error(
|
|
173
|
-
this.log.error(
|
|
189
|
+
this.log.error('No Account found');
|
|
190
|
+
this.log.error('All accounts: ' + res.data.currentUser.accounts);
|
|
191
|
+
this.log.error('Filtered accounts: ' + filteredAccounts);
|
|
174
192
|
return;
|
|
175
193
|
}
|
|
176
194
|
|
|
177
195
|
this.account = filteredAccounts[0];
|
|
178
196
|
})
|
|
179
197
|
.catch((error) => {
|
|
180
|
-
this.log.error(
|
|
198
|
+
this.log.error('Error while getting account');
|
|
181
199
|
this.log.error(error);
|
|
182
200
|
if (error.response) {
|
|
183
201
|
this.log.error(JSON.stringify(error.response.data));
|
|
184
|
-
if (error.response.data && JSON.stringify(error.response.data).indexOf(
|
|
185
|
-
this.log.error(
|
|
202
|
+
if (error.response.data && JSON.stringify(error.response.data).indexOf('apikey') !== -1) {
|
|
203
|
+
this.log.error('Wrong API Key. Please update API Key in adapter settings');
|
|
186
204
|
}
|
|
187
205
|
}
|
|
188
206
|
});
|
|
189
207
|
}
|
|
190
208
|
async getDeviceList() {
|
|
191
209
|
await this.requestClient({
|
|
192
|
-
method:
|
|
210
|
+
method: 'get',
|
|
193
211
|
url:
|
|
194
|
-
|
|
212
|
+
'https://api-wired-prod-1-euw1.wrd-aws.com/commerce/v1/accounts/' +
|
|
195
213
|
this.account.accountId +
|
|
196
|
-
|
|
214
|
+
'/vehicles?country=' +
|
|
197
215
|
this.country +
|
|
198
|
-
|
|
216
|
+
'&oms=false',
|
|
199
217
|
headers: {
|
|
200
218
|
apikey: this.apiKeyUpdate,
|
|
201
|
-
|
|
202
|
-
accept:
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
219
|
+
'content-type': 'application/json',
|
|
220
|
+
accept: '*/*',
|
|
221
|
+
'user-agent': this.userAgent,
|
|
222
|
+
'accept-language': 'de-de',
|
|
223
|
+
'x-gigya-id_token': this.session.id_token,
|
|
224
|
+
'X-Amzn-Trace-Id': this.buildTraceId(),
|
|
206
225
|
},
|
|
207
226
|
})
|
|
208
227
|
.then(async (res) => {
|
|
@@ -217,53 +236,54 @@ class Renault extends utils.Adapter {
|
|
|
217
236
|
|
|
218
237
|
this.ignoreState[device.vin] = [];
|
|
219
238
|
await this.setObjectNotExistsAsync(device.vin, {
|
|
220
|
-
type:
|
|
239
|
+
type: 'device',
|
|
221
240
|
common: {
|
|
222
241
|
name: name,
|
|
223
242
|
},
|
|
224
243
|
native: {},
|
|
225
244
|
});
|
|
226
|
-
await this.setObjectNotExistsAsync(device.vin +
|
|
227
|
-
type:
|
|
245
|
+
await this.setObjectNotExistsAsync(device.vin + '.remote', {
|
|
246
|
+
type: 'channel',
|
|
228
247
|
common: {
|
|
229
|
-
name:
|
|
248
|
+
name: 'Remote Controls',
|
|
230
249
|
},
|
|
231
250
|
native: {},
|
|
232
251
|
});
|
|
233
|
-
await this.setObjectNotExistsAsync(device.vin +
|
|
234
|
-
type:
|
|
252
|
+
await this.setObjectNotExistsAsync(device.vin + '.general', {
|
|
253
|
+
type: 'channel',
|
|
235
254
|
common: {
|
|
236
|
-
name:
|
|
255
|
+
name: 'WIRD NICHT AKTUALISIERT',
|
|
237
256
|
},
|
|
238
257
|
native: {},
|
|
239
258
|
});
|
|
240
259
|
|
|
241
260
|
const remoteArray = [
|
|
242
|
-
{ command:
|
|
243
|
-
{ command:
|
|
244
|
-
{ command:
|
|
245
|
-
{ command:
|
|
246
|
-
{ command:
|
|
247
|
-
{ command:
|
|
261
|
+
{ command: 'actions/hvac-start', name: 'True = Start, False = Stop' },
|
|
262
|
+
{ command: 'hvac-temperature', name: 'HVAC Temperature', type: 'number', role: 'value' },
|
|
263
|
+
{ command: 'actions/charging-start', name: 'True = Start, False = Stop' },
|
|
264
|
+
{ command: 'charge/pause-resume', name: 'True = Start, False = Stop' },
|
|
265
|
+
{ command: 'charge/start', name: 'True = Start, False = Stop' },
|
|
266
|
+
{ command: 'refresh', name: 'True = Refresh Data' },
|
|
248
267
|
];
|
|
249
268
|
remoteArray.forEach((remote) => {
|
|
250
|
-
this.setObjectNotExists(device.vin +
|
|
251
|
-
type:
|
|
269
|
+
this.setObjectNotExists(device.vin + '.remote.' + remote.command, {
|
|
270
|
+
type: 'state',
|
|
252
271
|
common: {
|
|
253
|
-
name: remote.name ||
|
|
254
|
-
type: remote.type ||
|
|
255
|
-
role: remote.role ||
|
|
272
|
+
name: remote.name || '',
|
|
273
|
+
type: remote.type || 'boolean',
|
|
274
|
+
role: remote.role || 'button',
|
|
256
275
|
write: true,
|
|
257
276
|
read: true,
|
|
258
277
|
},
|
|
259
278
|
native: {},
|
|
260
279
|
});
|
|
261
280
|
});
|
|
262
|
-
|
|
281
|
+
delete device.mileage;
|
|
282
|
+
this.json2iob.parse(device.vin + '.general', device);
|
|
263
283
|
}
|
|
264
284
|
})
|
|
265
285
|
.catch((error) => {
|
|
266
|
-
this.log.error(
|
|
286
|
+
this.log.error('Error while getting vehicle list');
|
|
267
287
|
this.log.error(error);
|
|
268
288
|
error.response && this.log.error(JSON.stringify(error.response.data));
|
|
269
289
|
});
|
|
@@ -271,154 +291,158 @@ class Renault extends utils.Adapter {
|
|
|
271
291
|
|
|
272
292
|
async updateDevices() {
|
|
273
293
|
if (!this.account.accountId) {
|
|
274
|
-
this.log.error(
|
|
294
|
+
this.log.error('No accountId found');
|
|
275
295
|
return;
|
|
276
296
|
}
|
|
277
|
-
const curDate = new Date().toISOString().split(
|
|
297
|
+
const curDate = new Date().toISOString().split('T')[0];
|
|
278
298
|
|
|
279
299
|
const statusArray = [
|
|
280
300
|
{
|
|
281
|
-
path:
|
|
301
|
+
path: 'battery-status',
|
|
282
302
|
url:
|
|
283
|
-
|
|
303
|
+
'https://api-wired-prod-1-euw1.wrd-aws.com/commerce/v1/accounts/' +
|
|
284
304
|
this.account.accountId +
|
|
285
|
-
|
|
305
|
+
'/kamereon/kca/car-adapter/v2/cars/$vin/battery-status?country=' +
|
|
286
306
|
this.country,
|
|
287
|
-
desc:
|
|
307
|
+
desc: 'Battery status of the car',
|
|
288
308
|
},
|
|
289
309
|
{
|
|
290
|
-
path:
|
|
310
|
+
path: 'battery-inhibition-status',
|
|
291
311
|
url:
|
|
292
|
-
|
|
312
|
+
'https://api-wired-prod-1-euw1.wrd-aws.com/commerce/v1/accounts/' +
|
|
293
313
|
this.account.accountId +
|
|
294
|
-
|
|
314
|
+
'/kamereon/kca/car-adapter/v1/cars/$vin/battery-inhibition-status?country=' +
|
|
295
315
|
this.country,
|
|
296
|
-
desc:
|
|
316
|
+
desc: 'Battery inhibition status of the car',
|
|
297
317
|
},
|
|
298
318
|
{
|
|
299
|
-
path:
|
|
319
|
+
path: 'cockpit',
|
|
300
320
|
url:
|
|
301
|
-
|
|
321
|
+
'https://api-wired-prod-1-euw1.wrd-aws.com/commerce/v1/accounts/' +
|
|
302
322
|
this.account.accountId +
|
|
303
|
-
|
|
323
|
+
'/kamereon/kca/car-adapter/v1/cars/$vin/cockpit?country=' +
|
|
304
324
|
this.country,
|
|
305
|
-
desc:
|
|
325
|
+
desc: 'Status of the car',
|
|
306
326
|
},
|
|
307
327
|
{
|
|
308
|
-
path:
|
|
328
|
+
path: 'cockpitv2',
|
|
309
329
|
url:
|
|
310
|
-
|
|
330
|
+
'https://api-wired-prod-1-euw1.wrd-aws.com/commerce/v1/accounts/' +
|
|
311
331
|
this.account.accountId +
|
|
312
|
-
|
|
332
|
+
'/kamereon/kca/car-adapter/v2/cars/$vin/cockpit?country=' +
|
|
313
333
|
this.country,
|
|
314
|
-
desc:
|
|
334
|
+
desc: 'Statusv2 of the car',
|
|
315
335
|
},
|
|
316
336
|
{
|
|
317
|
-
path:
|
|
337
|
+
path: 'charge-mode',
|
|
318
338
|
url:
|
|
319
|
-
|
|
339
|
+
'https://api-wired-prod-1-euw1.wrd-aws.com/commerce/v1/accounts/' +
|
|
320
340
|
this.account.accountId +
|
|
321
|
-
|
|
341
|
+
'/kamereon/kca/car-adapter/v1/cars/$vin/charge-mode?country=' +
|
|
322
342
|
this.country,
|
|
323
|
-
desc:
|
|
343
|
+
desc: 'Charge mode of the car',
|
|
324
344
|
},
|
|
325
345
|
{
|
|
326
|
-
path:
|
|
346
|
+
path: 'hvac-status',
|
|
327
347
|
url:
|
|
328
|
-
|
|
348
|
+
'https://api-wired-prod-1-euw1.wrd-aws.com/commerce/v1/accounts/' +
|
|
329
349
|
this.account.accountId +
|
|
330
|
-
|
|
350
|
+
'/kamereon/kca/car-adapter/v1/cars/$vin/hvac-status?country=' +
|
|
331
351
|
this.country,
|
|
332
|
-
desc:
|
|
352
|
+
desc: 'HVAC status of the car',
|
|
333
353
|
},
|
|
334
354
|
{
|
|
335
|
-
path:
|
|
355
|
+
path: 'hvac-settings',
|
|
336
356
|
url:
|
|
337
|
-
|
|
357
|
+
'https://api-wired-prod-1-euw1.wrd-aws.com/commerce/v1/accounts/' +
|
|
338
358
|
this.account.accountId +
|
|
339
|
-
|
|
359
|
+
'/kamereon/kca/car-adapter/v1/cars/$vin/hvac-settings?country=' +
|
|
340
360
|
this.country,
|
|
341
|
-
desc:
|
|
361
|
+
desc: 'HVAC settings of the car',
|
|
342
362
|
},
|
|
343
363
|
{
|
|
344
|
-
path:
|
|
364
|
+
path: 'charging-settings',
|
|
345
365
|
url:
|
|
346
|
-
|
|
366
|
+
'https://api-wired-prod-1-euw1.wrd-aws.com/commerce/v1/accounts/' +
|
|
347
367
|
this.account.accountId +
|
|
348
|
-
|
|
368
|
+
'/kamereon/kca/car-adapter/v1/cars/$vin/charging-settings?country=' +
|
|
349
369
|
this.country,
|
|
350
|
-
desc:
|
|
370
|
+
desc: 'Charging settings of the car',
|
|
351
371
|
},
|
|
372
|
+
|
|
352
373
|
{
|
|
353
|
-
path:
|
|
374
|
+
path: 'lock-status',
|
|
354
375
|
url:
|
|
355
|
-
|
|
376
|
+
'https://api-wired-prod-1-euw1.wrd-aws.com/commerce/v1/accounts/' +
|
|
356
377
|
this.account.accountId +
|
|
357
|
-
|
|
358
|
-
curDate +
|
|
359
|
-
"&country=" +
|
|
378
|
+
'/kamereon/kca/car-adapter/v1/cars/$vin/lock-status?country=' +
|
|
360
379
|
this.country,
|
|
361
|
-
desc:
|
|
380
|
+
desc: 'Lock status of the car',
|
|
362
381
|
},
|
|
363
382
|
{
|
|
364
|
-
path:
|
|
383
|
+
path: 'res-state',
|
|
365
384
|
url:
|
|
366
|
-
|
|
385
|
+
'https://api-wired-prod-1-euw1.wrd-aws.com/commerce/v1/accounts/' +
|
|
367
386
|
this.account.accountId +
|
|
368
|
-
|
|
369
|
-
curDate +
|
|
370
|
-
"&country=" +
|
|
387
|
+
'/kamereon/kca/car-adapter/v1/cars/$vin/res-state?country=' +
|
|
371
388
|
this.country,
|
|
372
|
-
desc:
|
|
389
|
+
desc: 'Res status of the car',
|
|
373
390
|
},
|
|
374
391
|
{
|
|
375
|
-
path:
|
|
392
|
+
path: 'location',
|
|
376
393
|
url:
|
|
377
|
-
|
|
394
|
+
'https://api-wired-prod-1-euw1.wrd-aws.com/commerce/v1/accounts/' +
|
|
378
395
|
this.account.accountId +
|
|
379
|
-
|
|
396
|
+
'/kamereon/kca/car-adapter/v1/cars/$vin/location?country=' +
|
|
380
397
|
this.country,
|
|
381
|
-
desc:
|
|
398
|
+
desc: 'Location of the car',
|
|
382
399
|
},
|
|
383
|
-
|
|
384
|
-
|
|
400
|
+
];
|
|
401
|
+
|
|
402
|
+
if (!this.config.disableChargeFetching) {
|
|
403
|
+
statusArray.push({
|
|
404
|
+
path: 'charge-history',
|
|
385
405
|
url:
|
|
386
|
-
|
|
406
|
+
'https://api-wired-prod-1-euw1.wrd-aws.com/commerce/v1/accounts/' +
|
|
387
407
|
this.account.accountId +
|
|
388
|
-
|
|
408
|
+
'/kamereon/kca/car-adapter/v1/cars/$vin/charge-history?type=day&start=1970-01-01&end=' +
|
|
409
|
+
curDate +
|
|
410
|
+
'&country=' +
|
|
389
411
|
this.country,
|
|
390
|
-
desc:
|
|
391
|
-
}
|
|
392
|
-
{
|
|
393
|
-
path:
|
|
412
|
+
desc: 'Charging history of the car',
|
|
413
|
+
});
|
|
414
|
+
statusArray.push({
|
|
415
|
+
path: 'charges',
|
|
394
416
|
url:
|
|
395
|
-
|
|
417
|
+
'https://api-wired-prod-1-euw1.wrd-aws.com/commerce/v1/accounts/' +
|
|
396
418
|
this.account.accountId +
|
|
397
|
-
|
|
419
|
+
'/kamereon/kca/car-adapter/v1/cars/$vin/charges?start=1970-01-01&end=' +
|
|
420
|
+
curDate +
|
|
421
|
+
'&country=' +
|
|
398
422
|
this.country,
|
|
399
|
-
desc:
|
|
400
|
-
}
|
|
401
|
-
|
|
423
|
+
desc: 'Charges of the car',
|
|
424
|
+
});
|
|
425
|
+
}
|
|
402
426
|
|
|
403
427
|
const headers = {
|
|
404
428
|
apikey: this.apiKeyUpdate,
|
|
405
|
-
|
|
406
|
-
accept:
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
429
|
+
'content-type': 'application/json',
|
|
430
|
+
accept: '*/*',
|
|
431
|
+
'user-agent': this.userAgent,
|
|
432
|
+
'accept-language': 'de-de',
|
|
433
|
+
'x-gigya-id_token': this.session.id_token,
|
|
410
434
|
};
|
|
411
435
|
for (const vin of this.deviceArray) {
|
|
412
436
|
for (const element of statusArray) {
|
|
413
437
|
if (this.ignoreState[vin] && this.ignoreState[vin].includes(element.path)) {
|
|
414
438
|
continue;
|
|
415
439
|
}
|
|
416
|
-
const url = element.url.replace(
|
|
440
|
+
const url = element.url.replace('$vin', vin);
|
|
417
441
|
|
|
418
442
|
await this.requestClient({
|
|
419
|
-
method:
|
|
443
|
+
method: 'get',
|
|
420
444
|
url: url,
|
|
421
|
-
headers: headers,
|
|
445
|
+
headers: { ...headers, 'X-Amzn-Trace-Id': this.buildTraceId() },
|
|
422
446
|
})
|
|
423
447
|
.then((res) => {
|
|
424
448
|
this.log.debug(JSON.stringify(res.data));
|
|
@@ -430,10 +454,10 @@ class Renault extends utils.Adapter {
|
|
|
430
454
|
data = res.data.data.attributes;
|
|
431
455
|
}
|
|
432
456
|
|
|
433
|
-
const forceIndex =
|
|
434
|
-
const preferedArrayName =
|
|
457
|
+
const forceIndex = undefined;
|
|
458
|
+
const preferedArrayName = undefined;
|
|
435
459
|
|
|
436
|
-
this.json2iob.parse(vin +
|
|
460
|
+
this.json2iob.parse(vin + '.' + element.path, data, {
|
|
437
461
|
forceIndex: forceIndex,
|
|
438
462
|
preferedArrayName: preferedArrayName,
|
|
439
463
|
channelName: element.desc,
|
|
@@ -443,7 +467,7 @@ class Renault extends utils.Adapter {
|
|
|
443
467
|
if (error.response) {
|
|
444
468
|
if (error.response.status === 401) {
|
|
445
469
|
error.response && this.log.debug(JSON.stringify(error.response.data));
|
|
446
|
-
this.log.info(element.path +
|
|
470
|
+
this.log.info(element.path + ' receive 401 error. Refresh Token in 60 seconds');
|
|
447
471
|
this.refreshTokenTimeout && clearTimeout(this.refreshTokenTimeout);
|
|
448
472
|
this.refreshTokenTimeout = setTimeout(() => {
|
|
449
473
|
this.refreshToken();
|
|
@@ -464,7 +488,7 @@ class Renault extends utils.Adapter {
|
|
|
464
488
|
this.ignoreState[vin] = [];
|
|
465
489
|
}
|
|
466
490
|
this.ignoreState[vin].push(element.path);
|
|
467
|
-
this.log.info(
|
|
491
|
+
this.log.info('Feature not found for ' + vin + '. Ignore ' + element.path + ' for updates.');
|
|
468
492
|
this.log.debug(error);
|
|
469
493
|
error.response && this.log.debug(JSON.stringify(error.response.data));
|
|
470
494
|
return;
|
|
@@ -485,42 +509,45 @@ class Renault extends utils.Adapter {
|
|
|
485
509
|
}
|
|
486
510
|
async refreshToken() {
|
|
487
511
|
if (!this.session_data) {
|
|
488
|
-
this.log.error(
|
|
512
|
+
this.log.error('No session found relogin');
|
|
489
513
|
await this.login();
|
|
490
514
|
return;
|
|
491
515
|
}
|
|
492
516
|
await this.requestClient({
|
|
493
|
-
method:
|
|
494
|
-
url:
|
|
517
|
+
method: 'post',
|
|
518
|
+
url: 'https://accounts.eu1.gigya.com/accounts.getJWT',
|
|
495
519
|
headers: {
|
|
496
|
-
|
|
497
|
-
Accept:
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
520
|
+
'User-Agent': this.userAgent,
|
|
521
|
+
Accept: '*/*',
|
|
522
|
+
'Accept-Language': 'de-de',
|
|
523
|
+
'Cache-Control': 'no-cache',
|
|
524
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
501
525
|
},
|
|
502
526
|
data: qs.stringify({
|
|
503
|
-
format:
|
|
527
|
+
format: 'json',
|
|
504
528
|
login_token: this.session_data.cookieValue,
|
|
505
|
-
sdk:
|
|
506
|
-
fields:
|
|
529
|
+
sdk: 'js_latest',
|
|
530
|
+
fields: 'data.personId,data.gigyaDataCenter',
|
|
507
531
|
apikey: this.apiKey,
|
|
508
|
-
expiration:
|
|
532
|
+
expiration: '3600',
|
|
509
533
|
}),
|
|
510
534
|
})
|
|
511
535
|
.then((res) => {
|
|
512
536
|
this.log.debug(JSON.stringify(res.data));
|
|
513
537
|
this.session = res.data;
|
|
514
|
-
this.setState(
|
|
538
|
+
this.setState('info.connection', true, true);
|
|
515
539
|
})
|
|
516
540
|
.catch((error) => {
|
|
517
|
-
this.log.error(
|
|
541
|
+
this.log.error('refresh token failed');
|
|
518
542
|
this.log.error(error);
|
|
519
543
|
error.response && this.log.error(JSON.stringify(error.response.data));
|
|
520
|
-
this.log.error(
|
|
521
|
-
this.reLoginTimeout = setTimeout(
|
|
522
|
-
|
|
523
|
-
|
|
544
|
+
this.log.error('Start relogin in 1min');
|
|
545
|
+
this.reLoginTimeout = setTimeout(
|
|
546
|
+
() => {
|
|
547
|
+
this.login();
|
|
548
|
+
},
|
|
549
|
+
1000 * 60 * 1,
|
|
550
|
+
);
|
|
524
551
|
});
|
|
525
552
|
}
|
|
526
553
|
sleep(ms) {
|
|
@@ -530,8 +557,8 @@ class Renault extends utils.Adapter {
|
|
|
530
557
|
if (!string) {
|
|
531
558
|
return;
|
|
532
559
|
}
|
|
533
|
-
string = string.replace(
|
|
534
|
-
string = string.replace(
|
|
560
|
+
string = string.replace('actions/', '');
|
|
561
|
+
string = string.replace('/', '-');
|
|
535
562
|
const camelC = string.replace(/-([a-z])/g, function (g) {
|
|
536
563
|
return g[1].toUpperCase();
|
|
537
564
|
});
|
|
@@ -543,7 +570,7 @@ class Renault extends utils.Adapter {
|
|
|
543
570
|
*/
|
|
544
571
|
onUnload(callback) {
|
|
545
572
|
try {
|
|
546
|
-
this.setState(
|
|
573
|
+
this.setState('info.connection', false, true);
|
|
547
574
|
clearTimeout(this.refreshTimeout);
|
|
548
575
|
this.reLoginTimeout && clearTimeout(this.reLoginTimeout);
|
|
549
576
|
this.refreshTokenTimeout && clearTimeout(this.refreshTokenTimeout);
|
|
@@ -551,6 +578,7 @@ class Renault extends utils.Adapter {
|
|
|
551
578
|
clearInterval(this.refreshTokenInterval);
|
|
552
579
|
callback();
|
|
553
580
|
} catch (e) {
|
|
581
|
+
this.log.error('Error onUnload: ' + e);
|
|
554
582
|
callback();
|
|
555
583
|
}
|
|
556
584
|
}
|
|
@@ -563,30 +591,30 @@ class Renault extends utils.Adapter {
|
|
|
563
591
|
async onStateChange(id, state) {
|
|
564
592
|
if (state) {
|
|
565
593
|
if (!state.ack) {
|
|
566
|
-
const deviceId = id.split(
|
|
567
|
-
const path = id.split(
|
|
568
|
-
if (path ===
|
|
594
|
+
const deviceId = id.split('.')[2];
|
|
595
|
+
const path = id.split('.')[4];
|
|
596
|
+
if (path === 'hvac-temperature') {
|
|
569
597
|
return;
|
|
570
598
|
}
|
|
571
|
-
if (path ===
|
|
572
|
-
this.log.info(
|
|
599
|
+
if (path === 'refresh') {
|
|
600
|
+
this.log.info('Force refresh');
|
|
573
601
|
this.updateDevices();
|
|
574
602
|
return;
|
|
575
603
|
}
|
|
576
604
|
if (!this.account) {
|
|
577
|
-
this.log.error(
|
|
605
|
+
this.log.error('No account found');
|
|
578
606
|
return;
|
|
579
607
|
}
|
|
580
|
-
const command = path.split(
|
|
581
|
-
let action = state.val ?
|
|
582
|
-
let midPart =
|
|
583
|
-
if (path ===
|
|
584
|
-
action = state.val ?
|
|
585
|
-
midPart =
|
|
608
|
+
const command = path.split('/')[1];
|
|
609
|
+
let action = state.val ? 'start' : 'cancel';
|
|
610
|
+
let midPart = 'kca/car-adapter/v1/cars/';
|
|
611
|
+
if (path === 'charge/pause-resume') {
|
|
612
|
+
action = state.val ? 'resume' : 'pause';
|
|
613
|
+
midPart = 'kcm/v1/vehicles/';
|
|
586
614
|
}
|
|
587
615
|
const data = { data: { type: this.toCamelCase(path), attributes: { action: action } } };
|
|
588
|
-
if (command ===
|
|
589
|
-
const temperatureState = await this.getStateAsync(deviceId +
|
|
616
|
+
if (command === 'hvac-start') {
|
|
617
|
+
const temperatureState = await this.getStateAsync(deviceId + '.remote.hvac-temperature');
|
|
590
618
|
if (temperatureState) {
|
|
591
619
|
data.data.attributes.targetTemperature = temperatureState.val ? temperatureState.val : 21;
|
|
592
620
|
} else {
|
|
@@ -594,27 +622,28 @@ class Renault extends utils.Adapter {
|
|
|
594
622
|
}
|
|
595
623
|
}
|
|
596
624
|
const url =
|
|
597
|
-
|
|
625
|
+
'https://api-wired-prod-1-euw1.wrd-aws.com/commerce/v1/accounts/' +
|
|
598
626
|
this.account.accountId +
|
|
599
|
-
|
|
627
|
+
'/kamereon/' +
|
|
600
628
|
midPart +
|
|
601
629
|
deviceId +
|
|
602
|
-
|
|
630
|
+
'/' +
|
|
603
631
|
path +
|
|
604
|
-
|
|
632
|
+
'?country=' +
|
|
605
633
|
this.country;
|
|
606
634
|
this.log.debug(JSON.stringify(data));
|
|
607
635
|
this.log.debug(url);
|
|
608
636
|
await this.requestClient({
|
|
609
|
-
method:
|
|
637
|
+
method: 'post',
|
|
610
638
|
url: url,
|
|
611
639
|
headers: {
|
|
612
640
|
apikey: this.apiKeyUpdate,
|
|
613
|
-
|
|
614
|
-
accept:
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
641
|
+
'content-type': 'application/vnd.api+json',
|
|
642
|
+
accept: '*/*',
|
|
643
|
+
'user-agent': this.userAgent,
|
|
644
|
+
'accept-language': 'de-de',
|
|
645
|
+
'x-gigya-id_token': this.session.id_token,
|
|
646
|
+
'X-Amzn-Trace-Id': this.buildTraceId(),
|
|
618
647
|
},
|
|
619
648
|
data: data,
|
|
620
649
|
})
|