iobroker.easee 2.0.0 → 3.0.0
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/README.md +4 -3
- package/admin/jsonConfig.json +11 -1
- package/io-package.json +15 -2
- package/lib/{enum.js → enum.ts} +8 -10
- package/lib/observations.ts +156 -0
- package/lib/{signalr-http-client.js → signalr-http-client.ts} +34 -12
- package/lib/tools.ts +120 -0
- package/{main.js → main.ts} +318 -139
- package/package.json +10 -9
- package/admin/index_m.html +0 -149
- package/admin/style.css +0 -32
- package/admin/words.js +0 -39
- package/lib/observations.js +0 -89
- package/lib/tools.js +0 -97
- package/admin/i18n/{de/translations.json → de.json} +10 -10
- package/admin/i18n/{en/translations.json → en.json} +10 -10
- package/admin/i18n/{es/translations.json → es.json} +10 -10
- package/admin/i18n/{fr/translations.json → fr.json} +10 -10
- package/admin/i18n/{it/translations.json → it.json} +10 -10
- package/admin/i18n/{nl/translations.json → nl.json} +10 -10
- package/admin/i18n/{pl/translations.json → pl.json} +10 -10
- package/admin/i18n/{pt/translations.json → pt.json} +10 -10
- package/admin/i18n/{ru/translations.json → ru.json} +10 -10
- package/admin/i18n/{uk/translations.json → uk.json} +10 -10
- package/admin/i18n/{zh-cn/translations.json → zh-cn.json} +10 -10
package/{main.js → main.ts}
RENAMED
|
@@ -1,34 +1,138 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const {
|
|
3
|
+
import { Adapter } from "@iobroker/adapter-core";
|
|
4
|
+
import axios from "axios";
|
|
5
|
+
import * as signalR from "@microsoft/signalr";
|
|
6
|
+
import * as objEnum from "./lib/enum.ts";
|
|
7
|
+
import AxiosSignalRHttpClient from "./lib/signalr-http-client.ts";
|
|
8
|
+
import {
|
|
10
9
|
CHARGER_STATE_OBSERVATION_IDS,
|
|
11
10
|
observationsToChargerState,
|
|
12
|
-
}
|
|
11
|
+
} from "./lib/observations.ts";
|
|
12
|
+
import type { ChargerObservationState } from "./lib/observations.ts";
|
|
13
|
+
|
|
14
|
+
type Timer = ioBroker.Timeout | undefined;
|
|
15
|
+
type Phase = "p1" | "p2" | "p3";
|
|
16
|
+
type AdapterOptions = ioBroker.AdapterOptions;
|
|
17
|
+
|
|
18
|
+
interface Charger {
|
|
19
|
+
id: string;
|
|
20
|
+
name: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
interface Site {
|
|
24
|
+
id: string;
|
|
25
|
+
currencyId?: string;
|
|
26
|
+
costPerKWh?: number;
|
|
27
|
+
costPerKwhExcludeVat?: number;
|
|
28
|
+
vat?: number;
|
|
29
|
+
circuits?: Array<{ id: string }>;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
interface ChargerConfig {
|
|
33
|
+
[key: string]: ioBroker.StateValue;
|
|
34
|
+
isEnabled: ioBroker.StateValue;
|
|
35
|
+
phaseMode: ioBroker.StateValue;
|
|
36
|
+
ledStripBrightness: ioBroker.StateValue;
|
|
37
|
+
smartButtonEnabled: ioBroker.StateValue;
|
|
38
|
+
wiFiSSID: ioBroker.StateValue;
|
|
39
|
+
maxChargerCurrent: ioBroker.StateValue;
|
|
40
|
+
circuitMaxCurrentP1: ioBroker.StateValue;
|
|
41
|
+
circuitMaxCurrentP2: ioBroker.StateValue;
|
|
42
|
+
circuitMaxCurrentP3: ioBroker.StateValue;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
interface ChargerSession {
|
|
46
|
+
year: number;
|
|
47
|
+
month: number;
|
|
48
|
+
totalEnergyUsage: number;
|
|
49
|
+
totalCost: number;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
interface RetryState {
|
|
53
|
+
delay: number;
|
|
54
|
+
retryAt: number;
|
|
55
|
+
inFlight: Promise<unknown> | null;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
interface RetryableError extends Error {
|
|
59
|
+
retryDeferred?: boolean;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
interface DynamicChargerState {
|
|
63
|
+
pendingValues: Partial<Record<Phase, number>>;
|
|
64
|
+
pendingSequences: Partial<Record<Phase, number>>;
|
|
65
|
+
latestSequences: Record<Phase, number>;
|
|
66
|
+
timer: Timer | null;
|
|
67
|
+
retryTimer: Timer | null;
|
|
68
|
+
retryResolve: (() => void) | null;
|
|
69
|
+
queue: Promise<void>;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
interface DynamicCircuitState {
|
|
73
|
+
values: Record<Phase, number>;
|
|
74
|
+
phaseSequences: Record<Phase, number>;
|
|
75
|
+
timer: Timer | null;
|
|
76
|
+
queue: Promise<void>;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
interface PendingRetry {
|
|
80
|
+
timer: Timer;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
interface ChargerValueSet {
|
|
84
|
+
p1: number;
|
|
85
|
+
p2: number;
|
|
86
|
+
p3: number;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
interface SignalRProductUpdate {
|
|
90
|
+
id: number;
|
|
91
|
+
mid: string;
|
|
92
|
+
dataType: number;
|
|
93
|
+
value: string | number | boolean;
|
|
94
|
+
}
|
|
13
95
|
|
|
14
96
|
//Eigene Variablen
|
|
15
97
|
const apiUrl = "https://api.easee.com";
|
|
16
98
|
const apiRequestTimeout = 30000;
|
|
17
99
|
const sessionRequestInterval = 7 * 60 * 1000;
|
|
18
100
|
const defaultSessionPollInterval = 60;
|
|
19
|
-
const adapterIntervals = {}; //halten von allen Intervallen
|
|
101
|
+
const adapterIntervals: Record<string, Timer | undefined> = {}; //halten von allen Intervallen
|
|
20
102
|
let accessToken = "";
|
|
21
103
|
let refreshToken = "";
|
|
22
104
|
let expireTime = Date.now();
|
|
23
105
|
let polltime = 30;
|
|
24
106
|
let logtype = false;
|
|
25
107
|
const tokenRefreshMarginSeconds = 60;
|
|
26
|
-
const arrCharger = [];
|
|
27
|
-
|
|
28
|
-
function getRateLimitDelay(error) {
|
|
29
|
-
const
|
|
30
|
-
const
|
|
31
|
-
|
|
108
|
+
const arrCharger: string[] = [];
|
|
109
|
+
|
|
110
|
+
function getRateLimitDelay(error: unknown): number {
|
|
111
|
+
const errorRecord = isRecord(error) ? error : undefined;
|
|
112
|
+
const responseRecord =
|
|
113
|
+
errorRecord && isRecord(errorRecord.response)
|
|
114
|
+
? errorRecord.response
|
|
115
|
+
: undefined;
|
|
116
|
+
const responseHeaders =
|
|
117
|
+
axios.isAxiosError(error) && error.response
|
|
118
|
+
? error.response.headers
|
|
119
|
+
: responseRecord?.headers;
|
|
120
|
+
const headers =
|
|
121
|
+
typeof responseHeaders === "object" && responseHeaders !== null
|
|
122
|
+
? (responseHeaders as Record<string, unknown>)
|
|
123
|
+
: undefined;
|
|
124
|
+
const header = (name: string): string | undefined => {
|
|
125
|
+
if (!headers) {
|
|
126
|
+
return undefined;
|
|
127
|
+
}
|
|
128
|
+
const value = headers[name] ?? headers[name.toLowerCase()];
|
|
129
|
+
if (typeof value === "string") {
|
|
130
|
+
return value;
|
|
131
|
+
}
|
|
132
|
+
return Array.isArray(value) && typeof value[0] === "string"
|
|
133
|
+
? value[0]
|
|
134
|
+
: undefined;
|
|
135
|
+
};
|
|
32
136
|
const retryAfter = header("retry-after");
|
|
33
137
|
if (retryAfter !== undefined) {
|
|
34
138
|
const seconds = Number(retryAfter);
|
|
@@ -56,48 +160,61 @@ function getRateLimitDelay(error) {
|
|
|
56
160
|
}
|
|
57
161
|
}
|
|
58
162
|
|
|
59
|
-
return
|
|
163
|
+
return (responseRecord?.status ??
|
|
164
|
+
(axios.isAxiosError(error) ? error.response?.status : undefined)) === 429
|
|
165
|
+
? sessionRequestInterval
|
|
166
|
+
: 0;
|
|
60
167
|
}
|
|
61
168
|
|
|
62
|
-
function errorMessage(error) {
|
|
169
|
+
function errorMessage(error: unknown): string {
|
|
63
170
|
return error instanceof Error ? error.message : String(error);
|
|
64
171
|
}
|
|
65
172
|
|
|
66
|
-
|
|
67
|
-
|
|
173
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
174
|
+
return typeof value === "object" && value !== null;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function isRetryableError(error: unknown): error is RetryableError {
|
|
178
|
+
return (
|
|
179
|
+
error instanceof Error && (error as RetryableError).retryDeferred === true
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
class Easee extends Adapter {
|
|
184
|
+
signalRConnection: signalR.HubConnection | null = null;
|
|
185
|
+
signalRSubscribedChargers = new Set<string>();
|
|
186
|
+
signalRSubscriptionPromises = new Map<string, Promise<void>>();
|
|
187
|
+
unloading = false;
|
|
188
|
+
apiRetryState = new Map<string, RetryState>();
|
|
189
|
+
pendingSiteConfigRetries = new Map<string, PendingRetry>();
|
|
190
|
+
dynamicCircuitCurrentByCharger = new Map<string, DynamicChargerState>();
|
|
191
|
+
dynamicCircuitCurrentByCircuit = new Map<string, DynamicCircuitState>();
|
|
192
|
+
dynamicCircuitCurrentSequence = 0;
|
|
193
|
+
circuitMaxCurrentByCircuit = new Map<string, number>();
|
|
194
|
+
circuitMaxCurrentSequence = 0;
|
|
195
|
+
sessionChargers: string[] = [];
|
|
196
|
+
sessionCursor = 0;
|
|
197
|
+
sessionPollTimer: Timer | null = null;
|
|
198
|
+
sessionInFlight: Promise<void> | null = null;
|
|
199
|
+
sessionAbortController: AbortController | null = null;
|
|
200
|
+
sessionLastRequestAt: number | null = null;
|
|
201
|
+
sessionRetryAt = 0;
|
|
202
|
+
sessionPollMode: "auto" | "manual" = "auto";
|
|
203
|
+
sessionManualInterval = defaultSessionPollInterval;
|
|
204
|
+
|
|
205
|
+
constructor(options: AdapterOptions = { name: "easee" }) {
|
|
68
206
|
super({
|
|
69
207
|
...options,
|
|
70
208
|
name: "easee",
|
|
71
|
-
});
|
|
209
|
+
} as never);
|
|
72
210
|
this.on("ready", this.onReady.bind(this));
|
|
73
211
|
this.on("stateChange", this.onStateChange.bind(this));
|
|
74
212
|
this.on("unload", this.onUnload.bind(this));
|
|
75
|
-
this.signalRConnection = null;
|
|
76
|
-
this.signalRSubscribedChargers = new Set();
|
|
77
|
-
this.signalRSubscriptionPromises = new Map();
|
|
78
|
-
this.signalRSubscriptionPromises = new Map();
|
|
79
|
-
this.unloading = false;
|
|
80
|
-
this.apiRetryState = new Map();
|
|
81
|
-
this.pendingSiteConfigRetries = new Map();
|
|
82
|
-
this.dynamicCircuitCurrentByCharger = new Map();
|
|
83
|
-
this.dynamicCircuitCurrentByCircuit = new Map();
|
|
84
|
-
this.dynamicCircuitCurrentSequence = 0;
|
|
85
|
-
this.circuitMaxCurrentByCircuit = new Map();
|
|
86
|
-
this.circuitMaxCurrentSequence = 0;
|
|
87
|
-
this.sessionChargers = [];
|
|
88
|
-
this.sessionCursor = 0;
|
|
89
|
-
this.sessionPollTimer = null;
|
|
90
|
-
this.sessionInFlight = null;
|
|
91
|
-
this.sessionAbortController = null;
|
|
92
|
-
this.sessionLastRequestAt = null;
|
|
93
|
-
this.sessionRetryAt = 0;
|
|
94
|
-
this.sessionPollMode = "auto";
|
|
95
|
-
this.sessionManualInterval = defaultSessionPollInterval;
|
|
96
213
|
}
|
|
97
214
|
/**
|
|
98
215
|
* SignalR
|
|
99
216
|
*/
|
|
100
|
-
async startSignal() {
|
|
217
|
+
async startSignal(): Promise<void> {
|
|
101
218
|
if (this.unloading || this.signalRConnection !== null) {
|
|
102
219
|
return;
|
|
103
220
|
}
|
|
@@ -112,7 +229,7 @@ class Easee extends utils.Adapter {
|
|
|
112
229
|
.build();
|
|
113
230
|
this.signalRConnection = connection;
|
|
114
231
|
|
|
115
|
-
connection.on("ProductUpdate", (data) => {
|
|
232
|
+
connection.on("ProductUpdate", (data: SignalRProductUpdate) => {
|
|
116
233
|
//haben einen neuen Wert über SignalR erhalten
|
|
117
234
|
const data_name = objEnum.getNameByEnum(data.id);
|
|
118
235
|
if (data_name == undefined) {
|
|
@@ -129,10 +246,10 @@ class Easee extends utils.Adapter {
|
|
|
129
246
|
data.value = data.value == "1";
|
|
130
247
|
break;
|
|
131
248
|
case 3:
|
|
132
|
-
data.value = parseFloat(data.value);
|
|
249
|
+
data.value = parseFloat(String(data.value));
|
|
133
250
|
break;
|
|
134
251
|
case 4:
|
|
135
|
-
data.value = parseInt(data.value);
|
|
252
|
+
data.value = parseInt(String(data.value));
|
|
136
253
|
break;
|
|
137
254
|
//case 6: JSON
|
|
138
255
|
}
|
|
@@ -174,7 +291,7 @@ class Easee extends utils.Adapter {
|
|
|
174
291
|
}
|
|
175
292
|
}
|
|
176
293
|
|
|
177
|
-
async subscribeChargerToSignalR(chargerId) {
|
|
294
|
+
async subscribeChargerToSignalR(chargerId: string): Promise<void> {
|
|
178
295
|
const connection = this.signalRConnection;
|
|
179
296
|
if (
|
|
180
297
|
this.unloading ||
|
|
@@ -212,12 +329,12 @@ class Easee extends utils.Adapter {
|
|
|
212
329
|
return subscription;
|
|
213
330
|
}
|
|
214
331
|
|
|
215
|
-
scheduleSignalRReconnect() {
|
|
332
|
+
scheduleSignalRReconnect(): void {
|
|
216
333
|
if (this.unloading) {
|
|
217
334
|
return;
|
|
218
335
|
}
|
|
219
|
-
clearTimeout(adapterIntervals.signalRReconnect);
|
|
220
|
-
adapterIntervals.signalRReconnect = setTimeout(() => {
|
|
336
|
+
this.clearTimeout(adapterIntervals.signalRReconnect);
|
|
337
|
+
adapterIntervals.signalRReconnect = this.setTimeout(() => {
|
|
221
338
|
this.startSignal();
|
|
222
339
|
}, 30000);
|
|
223
340
|
}
|
|
@@ -225,7 +342,7 @@ class Easee extends utils.Adapter {
|
|
|
225
342
|
/**
|
|
226
343
|
* Starten den Adapter
|
|
227
344
|
*/
|
|
228
|
-
async onReady() {
|
|
345
|
+
async onReady(): Promise<void> {
|
|
229
346
|
//initial Status melden
|
|
230
347
|
await this.setStateAsync("info.connection", false, true);
|
|
231
348
|
|
|
@@ -245,7 +362,10 @@ class Easee extends utils.Adapter {
|
|
|
245
362
|
const lastSessionRequest = await this.getStateAsync(
|
|
246
363
|
"info.sessionPollLastRequest",
|
|
247
364
|
);
|
|
248
|
-
if (
|
|
365
|
+
if (
|
|
366
|
+
typeof lastSessionRequest?.val === "number" &&
|
|
367
|
+
Number.isFinite(lastSessionRequest.val)
|
|
368
|
+
) {
|
|
249
369
|
this.sessionLastRequestAt = lastSessionRequest.val;
|
|
250
370
|
}
|
|
251
371
|
|
|
@@ -294,7 +414,7 @@ class Easee extends utils.Adapter {
|
|
|
294
414
|
}
|
|
295
415
|
}
|
|
296
416
|
|
|
297
|
-
configureSessionPolling() {
|
|
417
|
+
configureSessionPolling(): void {
|
|
298
418
|
this.sessionPollMode =
|
|
299
419
|
this.config.sessionPollMode === "manual" ? "manual" : "auto";
|
|
300
420
|
const configuredInterval = Number(this.config.sessionPollInterval);
|
|
@@ -312,26 +432,34 @@ class Easee extends utils.Adapter {
|
|
|
312
432
|
}
|
|
313
433
|
|
|
314
434
|
// Clear all Timeouts and inform users
|
|
315
|
-
onUnload(callback) {
|
|
435
|
+
onUnload(callback: () => void): void {
|
|
316
436
|
this.unloading = true;
|
|
317
|
-
clearTimeout(adapterIntervals.readAllStates);
|
|
318
|
-
|
|
437
|
+
this.clearTimeout(adapterIntervals.readAllStates);
|
|
438
|
+
if (this.sessionPollTimer) {
|
|
439
|
+
this.clearTimeout(this.sessionPollTimer);
|
|
440
|
+
}
|
|
319
441
|
this.sessionPollTimer = null;
|
|
320
442
|
this.sessionAbortController?.abort();
|
|
321
443
|
const sessionShutdown = this.sessionInFlight;
|
|
322
444
|
for (const chargerState of this.dynamicCircuitCurrentByCharger.values()) {
|
|
323
|
-
|
|
324
|
-
|
|
445
|
+
if (chargerState.timer) {
|
|
446
|
+
this.clearTimeout(chargerState.timer);
|
|
447
|
+
}
|
|
448
|
+
if (chargerState.retryTimer) {
|
|
449
|
+
this.clearTimeout(chargerState.retryTimer);
|
|
450
|
+
}
|
|
325
451
|
chargerState.retryResolve?.();
|
|
326
452
|
}
|
|
327
453
|
this.dynamicCircuitCurrentByCharger.clear();
|
|
328
454
|
for (const circuitState of this.dynamicCircuitCurrentByCircuit.values()) {
|
|
329
|
-
|
|
455
|
+
if (circuitState.timer) {
|
|
456
|
+
this.clearTimeout(circuitState.timer);
|
|
457
|
+
}
|
|
330
458
|
}
|
|
331
459
|
this.dynamicCircuitCurrentByCircuit.clear();
|
|
332
|
-
clearTimeout(adapterIntervals.signalRReconnect);
|
|
460
|
+
this.clearTimeout(adapterIntervals.signalRReconnect);
|
|
333
461
|
for (const retry of this.pendingSiteConfigRetries.values()) {
|
|
334
|
-
clearTimeout(retry.timer);
|
|
462
|
+
this.clearTimeout(retry.timer);
|
|
335
463
|
}
|
|
336
464
|
this.pendingSiteConfigRetries.clear();
|
|
337
465
|
const signalRShutdown = Promise.resolve(
|
|
@@ -355,17 +483,20 @@ class Easee extends utils.Adapter {
|
|
|
355
483
|
});
|
|
356
484
|
}
|
|
357
485
|
|
|
358
|
-
async requestWithBackoff(
|
|
486
|
+
async requestWithBackoff<T>(
|
|
487
|
+
key: string,
|
|
488
|
+
requestFn: () => Promise<T>,
|
|
489
|
+
): Promise<T> {
|
|
359
490
|
let retryState = this.apiRetryState.get(key);
|
|
360
491
|
if (!retryState) {
|
|
361
492
|
retryState = { delay: 30000, retryAt: 0, inFlight: null };
|
|
362
493
|
this.apiRetryState.set(key, retryState);
|
|
363
494
|
}
|
|
364
495
|
if (retryState.inFlight) {
|
|
365
|
-
return retryState.inFlight;
|
|
496
|
+
return (await retryState.inFlight) as T;
|
|
366
497
|
}
|
|
367
498
|
if (retryState.retryAt > Date.now()) {
|
|
368
|
-
const error = new Error(`Retry deferred for ${key}`);
|
|
499
|
+
const error: RetryableError = new Error(`Retry deferred for ${key}`);
|
|
369
500
|
error.retryDeferred = true;
|
|
370
501
|
throw error;
|
|
371
502
|
}
|
|
@@ -391,24 +522,24 @@ class Easee extends utils.Adapter {
|
|
|
391
522
|
this.log.warn(
|
|
392
523
|
`Easee API request failed for ${key}; retrying after ${Math.ceil(delay / 1000)} seconds: ${errorMessage(error)}`,
|
|
393
524
|
);
|
|
394
|
-
const retryError = new Error(errorMessage(error));
|
|
525
|
+
const retryError: RetryableError = new Error(errorMessage(error));
|
|
395
526
|
retryError.retryDeferred = true;
|
|
396
527
|
throw retryError;
|
|
397
528
|
} finally {
|
|
398
529
|
retryState.inFlight = null;
|
|
399
530
|
}
|
|
400
531
|
})();
|
|
401
|
-
return retryState.inFlight;
|
|
532
|
+
return (await retryState.inFlight) as T;
|
|
402
533
|
}
|
|
403
534
|
|
|
404
535
|
async updateSiteConfigWithRetry(
|
|
405
|
-
chargerId,
|
|
406
|
-
stateId,
|
|
407
|
-
description,
|
|
408
|
-
update
|
|
409
|
-
sequence,
|
|
536
|
+
chargerId: string,
|
|
537
|
+
stateId: string,
|
|
538
|
+
description: string,
|
|
539
|
+
update: (site: Site) => Promise<void>,
|
|
540
|
+
sequence: number | undefined,
|
|
410
541
|
requireCircuit = true,
|
|
411
|
-
) {
|
|
542
|
+
): Promise<void> {
|
|
412
543
|
if (this.unloading) {
|
|
413
544
|
return;
|
|
414
545
|
}
|
|
@@ -420,20 +551,22 @@ class Easee extends utils.Adapter {
|
|
|
420
551
|
return;
|
|
421
552
|
}
|
|
422
553
|
if (requireCircuit) {
|
|
423
|
-
const circuitKey = `${site.id}:${site.circuits[0].id}`;
|
|
554
|
+
const circuitKey = `${site.id}:${site.circuits![0].id}`;
|
|
424
555
|
const latestSequence =
|
|
425
556
|
this.circuitMaxCurrentByCircuit.get(circuitKey) || 0;
|
|
426
|
-
if (sequence < latestSequence) {
|
|
557
|
+
if (sequence !== undefined && sequence < latestSequence) {
|
|
427
558
|
this.log.info(
|
|
428
559
|
`Discarded superseded ${description} for ${circuitKey}`,
|
|
429
560
|
);
|
|
430
561
|
return;
|
|
431
562
|
}
|
|
432
|
-
|
|
563
|
+
if (sequence !== undefined) {
|
|
564
|
+
this.circuitMaxCurrentByCircuit.set(circuitKey, sequence);
|
|
565
|
+
}
|
|
433
566
|
}
|
|
434
567
|
await update(site);
|
|
435
568
|
} catch (error) {
|
|
436
|
-
if (!error
|
|
569
|
+
if (!isRetryableError(error) || this.unloading) {
|
|
437
570
|
this.log.error(`${description} error: ${errorMessage(error)}`);
|
|
438
571
|
return;
|
|
439
572
|
}
|
|
@@ -441,7 +574,7 @@ class Easee extends utils.Adapter {
|
|
|
441
574
|
const retryKey = `${chargerId}:${stateId}`;
|
|
442
575
|
const existingRetry = this.pendingSiteConfigRetries.get(retryKey);
|
|
443
576
|
if (existingRetry) {
|
|
444
|
-
clearTimeout(existingRetry.timer);
|
|
577
|
+
this.clearTimeout(existingRetry.timer);
|
|
445
578
|
}
|
|
446
579
|
|
|
447
580
|
const siteRetry = this.apiRetryState.get(`charger site ${chargerId}`);
|
|
@@ -449,7 +582,7 @@ class Easee extends utils.Adapter {
|
|
|
449
582
|
0,
|
|
450
583
|
(siteRetry?.retryAt || Date.now()) - Date.now(),
|
|
451
584
|
);
|
|
452
|
-
const timer = setTimeout(() => {
|
|
585
|
+
const timer = this.setTimeout(() => {
|
|
453
586
|
this.pendingSiteConfigRetries.delete(retryKey);
|
|
454
587
|
this.updateSiteConfigWithRetry(
|
|
455
588
|
chargerId,
|
|
@@ -468,14 +601,14 @@ class Easee extends utils.Adapter {
|
|
|
468
601
|
}
|
|
469
602
|
|
|
470
603
|
async updateDynamicCircuitWithRetry(
|
|
471
|
-
chargerId,
|
|
472
|
-
chargerState,
|
|
473
|
-
changedValues,
|
|
474
|
-
phaseSequences,
|
|
475
|
-
) {
|
|
604
|
+
chargerId: string,
|
|
605
|
+
chargerState: DynamicChargerState,
|
|
606
|
+
changedValues: Partial<Record<Phase, number>>,
|
|
607
|
+
phaseSequences: Partial<Record<Phase, number>>,
|
|
608
|
+
): Promise<void> {
|
|
476
609
|
while (!this.unloading) {
|
|
477
610
|
if (
|
|
478
|
-
Object.entries(phaseSequences).some(
|
|
611
|
+
(Object.entries(phaseSequences) as [Phase, number][]).some(
|
|
479
612
|
([phase, sequence]) =>
|
|
480
613
|
chargerState.latestSequences[phase] !== sequence,
|
|
481
614
|
)
|
|
@@ -495,7 +628,7 @@ class Easee extends utils.Adapter {
|
|
|
495
628
|
}
|
|
496
629
|
|
|
497
630
|
if (
|
|
498
|
-
Object.entries(phaseSequences).some(
|
|
631
|
+
(Object.entries(phaseSequences) as [Phase, number][]).some(
|
|
499
632
|
([phase, sequence]) =>
|
|
500
633
|
chargerState.latestSequences[phase] !== sequence,
|
|
501
634
|
)
|
|
@@ -519,8 +652,14 @@ class Easee extends utils.Adapter {
|
|
|
519
652
|
this.dynamicCircuitCurrentByCircuit.set(circuitKey, circuitState);
|
|
520
653
|
}
|
|
521
654
|
let updated = false;
|
|
522
|
-
for (const [phase, value] of Object.entries(changedValues)
|
|
655
|
+
for (const [phase, value] of Object.entries(changedValues) as [
|
|
656
|
+
Phase,
|
|
657
|
+
number,
|
|
658
|
+
][]) {
|
|
523
659
|
const sequence = phaseSequences[phase];
|
|
660
|
+
if (sequence === undefined) {
|
|
661
|
+
continue;
|
|
662
|
+
}
|
|
524
663
|
if (sequence >= circuitState.phaseSequences[phase]) {
|
|
525
664
|
circuitState.values[phase] = value;
|
|
526
665
|
circuitState.phaseSequences[phase] = sequence;
|
|
@@ -534,7 +673,7 @@ class Easee extends utils.Adapter {
|
|
|
534
673
|
return;
|
|
535
674
|
}
|
|
536
675
|
if (circuitState.timer === null) {
|
|
537
|
-
circuitState.timer = setTimeout(() => {
|
|
676
|
+
circuitState.timer = this.setTimeout(() => {
|
|
538
677
|
circuitState.timer = null;
|
|
539
678
|
const currentValues = { ...circuitState.values };
|
|
540
679
|
circuitState.values = { p1: 0, p2: 0, p3: 0 };
|
|
@@ -558,7 +697,7 @@ class Easee extends utils.Adapter {
|
|
|
558
697
|
}
|
|
559
698
|
return;
|
|
560
699
|
} catch (error) {
|
|
561
|
-
if (!error
|
|
700
|
+
if (!isRetryableError(error) || this.unloading) {
|
|
562
701
|
this.log.error(
|
|
563
702
|
`Dynamic circuit current update error: ${errorMessage(error)}`,
|
|
564
703
|
);
|
|
@@ -570,9 +709,9 @@ class Easee extends utils.Adapter {
|
|
|
570
709
|
0,
|
|
571
710
|
(siteRetry?.retryAt || Date.now()) - Date.now(),
|
|
572
711
|
);
|
|
573
|
-
await new Promise((resolve) => {
|
|
712
|
+
await new Promise<void>((resolve) => {
|
|
574
713
|
chargerState.retryResolve = resolve;
|
|
575
|
-
chargerState.retryTimer = setTimeout(resolve, delay);
|
|
714
|
+
chargerState.retryTimer = this.setTimeout(resolve, delay);
|
|
576
715
|
});
|
|
577
716
|
chargerState.retryResolve = null;
|
|
578
717
|
chargerState.retryTimer = null;
|
|
@@ -581,7 +720,7 @@ class Easee extends utils.Adapter {
|
|
|
581
720
|
}
|
|
582
721
|
|
|
583
722
|
/*****************************************************************************************/
|
|
584
|
-
async readAllStates() {
|
|
723
|
+
async readAllStates(): Promise<void> {
|
|
585
724
|
if (this.unloading) {
|
|
586
725
|
return;
|
|
587
726
|
}
|
|
@@ -648,7 +787,7 @@ class Easee extends utils.Adapter {
|
|
|
648
787
|
//Setzen die Config zum Charger
|
|
649
788
|
await this.setConfigStatus(charger, tmpChargerConfig, tmpChargerSite);
|
|
650
789
|
} catch (error) {
|
|
651
|
-
if (error
|
|
790
|
+
if (isRetryableError(error)) {
|
|
652
791
|
continue;
|
|
653
792
|
}
|
|
654
793
|
if (typeof error === "string") {
|
|
@@ -673,19 +812,17 @@ class Easee extends utils.Adapter {
|
|
|
673
812
|
true,
|
|
674
813
|
);
|
|
675
814
|
if (!this.unloading) {
|
|
676
|
-
adapterIntervals.readAllStates = setTimeout(
|
|
815
|
+
adapterIntervals.readAllStates = this.setTimeout(
|
|
677
816
|
this.readAllStates.bind(this),
|
|
678
817
|
polltime * 1000,
|
|
679
818
|
);
|
|
680
819
|
}
|
|
681
820
|
}
|
|
682
821
|
|
|
683
|
-
updateSessionChargers(chargers) {
|
|
822
|
+
updateSessionChargers(chargers: Charger[]): void {
|
|
684
823
|
const nextCharger = this.sessionChargers[this.sessionCursor];
|
|
685
824
|
const previousChargers = this.sessionChargers;
|
|
686
|
-
this.sessionChargers = [
|
|
687
|
-
...new Set((chargers || []).map((charger) => charger.id)),
|
|
688
|
-
];
|
|
825
|
+
this.sessionChargers = [...new Set(chargers.map((charger) => charger.id))];
|
|
689
826
|
const changed =
|
|
690
827
|
previousChargers.length !== this.sessionChargers.length ||
|
|
691
828
|
previousChargers.some(
|
|
@@ -702,7 +839,9 @@ class Easee extends utils.Adapter {
|
|
|
702
839
|
});
|
|
703
840
|
|
|
704
841
|
if (!this.sessionChargers.length) {
|
|
705
|
-
|
|
842
|
+
if (this.sessionPollTimer) {
|
|
843
|
+
this.clearTimeout(this.sessionPollTimer);
|
|
844
|
+
}
|
|
706
845
|
this.sessionPollTimer = null;
|
|
707
846
|
return;
|
|
708
847
|
}
|
|
@@ -712,7 +851,7 @@ class Easee extends utils.Adapter {
|
|
|
712
851
|
? 0
|
|
713
852
|
: Math.max(
|
|
714
853
|
0,
|
|
715
|
-
this.sessionLastRequestAt +
|
|
854
|
+
(this.sessionLastRequestAt ?? 0) +
|
|
716
855
|
this.getSessionRequestInterval() -
|
|
717
856
|
Date.now(),
|
|
718
857
|
);
|
|
@@ -720,7 +859,7 @@ class Easee extends utils.Adapter {
|
|
|
720
859
|
}
|
|
721
860
|
}
|
|
722
861
|
|
|
723
|
-
async updateSessionPollInfo() {
|
|
862
|
+
async updateSessionPollInfo(): Promise<void> {
|
|
724
863
|
const chargerCount = this.sessionChargers.length;
|
|
725
864
|
if (!chargerCount) {
|
|
726
865
|
return;
|
|
@@ -745,7 +884,7 @@ class Easee extends utils.Adapter {
|
|
|
745
884
|
]);
|
|
746
885
|
}
|
|
747
886
|
|
|
748
|
-
getSessionRequestInterval() {
|
|
887
|
+
getSessionRequestInterval(): number {
|
|
749
888
|
const chargerCount = this.sessionChargers.length;
|
|
750
889
|
if (!chargerCount) {
|
|
751
890
|
return sessionRequestInterval;
|
|
@@ -760,7 +899,7 @@ class Easee extends utils.Adapter {
|
|
|
760
899
|
);
|
|
761
900
|
}
|
|
762
901
|
|
|
763
|
-
scheduleSessionPoll(delay) {
|
|
902
|
+
scheduleSessionPoll(delay: number): void {
|
|
764
903
|
if (
|
|
765
904
|
this.unloading ||
|
|
766
905
|
!this.sessionChargers.length ||
|
|
@@ -768,8 +907,10 @@ class Easee extends utils.Adapter {
|
|
|
768
907
|
) {
|
|
769
908
|
return;
|
|
770
909
|
}
|
|
771
|
-
|
|
772
|
-
|
|
910
|
+
if (this.sessionPollTimer) {
|
|
911
|
+
this.clearTimeout(this.sessionPollTimer);
|
|
912
|
+
}
|
|
913
|
+
this.sessionPollTimer = this.setTimeout(() => {
|
|
773
914
|
this.sessionPollTimer = null;
|
|
774
915
|
this.pollNextSession().catch((error) => {
|
|
775
916
|
this.log.warn(`Session polling failed: ${errorMessage(error)}`);
|
|
@@ -777,7 +918,7 @@ class Easee extends utils.Adapter {
|
|
|
777
918
|
}, delay);
|
|
778
919
|
}
|
|
779
920
|
|
|
780
|
-
async pollNextSession() {
|
|
921
|
+
async pollNextSession(): Promise<void> {
|
|
781
922
|
if (
|
|
782
923
|
this.unloading ||
|
|
783
924
|
this.sessionInFlight ||
|
|
@@ -861,7 +1002,7 @@ class Easee extends utils.Adapter {
|
|
|
861
1002
|
this.sessionAbortController = null;
|
|
862
1003
|
const delay = Math.max(
|
|
863
1004
|
0,
|
|
864
|
-
this.sessionLastRequestAt +
|
|
1005
|
+
(this.sessionLastRequestAt ?? 0) +
|
|
865
1006
|
this.getSessionRequestInterval() -
|
|
866
1007
|
Date.now(),
|
|
867
1008
|
);
|
|
@@ -873,7 +1014,7 @@ class Easee extends utils.Adapter {
|
|
|
873
1014
|
}
|
|
874
1015
|
|
|
875
1016
|
//Is called if a subscribed state changes
|
|
876
|
-
onStateChange(id, state) {
|
|
1017
|
+
onStateChange(id: string, state: ioBroker.State | null | undefined): void {
|
|
877
1018
|
if (state) {
|
|
878
1019
|
// The state was changed
|
|
879
1020
|
this.log.debug(`state ${id} changed: ${state.val} (ack = ${state.ack})`);
|
|
@@ -898,7 +1039,7 @@ class Easee extends utils.Adapter {
|
|
|
898
1039
|
|
|
899
1040
|
await this.changeMaxCircuitConfig(
|
|
900
1041
|
site.id,
|
|
901
|
-
site.circuits[0].id,
|
|
1042
|
+
site.circuits![0].id,
|
|
902
1043
|
state.val,
|
|
903
1044
|
);
|
|
904
1045
|
this.log.debug("Changes sent to API");
|
|
@@ -925,7 +1066,7 @@ class Easee extends utils.Adapter {
|
|
|
925
1066
|
};
|
|
926
1067
|
this.dynamicCircuitCurrentByCharger.set(chargerId, currentState);
|
|
927
1068
|
}
|
|
928
|
-
let phase;
|
|
1069
|
+
let phase: Phase | undefined;
|
|
929
1070
|
switch (tmpControl[4]) {
|
|
930
1071
|
case "dynamicCircuitCurrentP1":
|
|
931
1072
|
phase = "p1";
|
|
@@ -937,13 +1078,18 @@ class Easee extends utils.Adapter {
|
|
|
937
1078
|
phase = "p3";
|
|
938
1079
|
break;
|
|
939
1080
|
}
|
|
1081
|
+
if (!phase) {
|
|
1082
|
+
return;
|
|
1083
|
+
}
|
|
940
1084
|
currentState.pendingValues[phase] = Number(state.val);
|
|
941
1085
|
currentState.pendingSequences[phase] = ++this
|
|
942
1086
|
.dynamicCircuitCurrentSequence;
|
|
943
1087
|
currentState.latestSequences[phase] =
|
|
944
|
-
currentState.pendingSequences[phase];
|
|
945
|
-
|
|
946
|
-
|
|
1088
|
+
currentState.pendingSequences[phase] ?? 0;
|
|
1089
|
+
if (currentState.timer) {
|
|
1090
|
+
this.clearTimeout(currentState.timer);
|
|
1091
|
+
}
|
|
1092
|
+
currentState.timer = this.setTimeout(() => {
|
|
947
1093
|
currentState.timer = null;
|
|
948
1094
|
const changedValues = { ...currentState.pendingValues };
|
|
949
1095
|
const phaseSequences = { ...currentState.pendingSequences };
|
|
@@ -1053,7 +1199,10 @@ class Easee extends utils.Adapter {
|
|
|
1053
1199
|
***********************************************************************/
|
|
1054
1200
|
|
|
1055
1201
|
//Setzen alle Status für Charger
|
|
1056
|
-
async setNewStatusToCharger(
|
|
1202
|
+
async setNewStatusToCharger(
|
|
1203
|
+
charger: Charger,
|
|
1204
|
+
charger_states: ChargerObservationState,
|
|
1205
|
+
): Promise<void> {
|
|
1057
1206
|
await this.setStateAsync(`${charger.id}.name`, charger.name, true);
|
|
1058
1207
|
await this.setStateAsync(
|
|
1059
1208
|
`${charger.id}.status.cableLocked`,
|
|
@@ -1218,7 +1367,11 @@ class Easee extends utils.Adapter {
|
|
|
1218
1367
|
}
|
|
1219
1368
|
|
|
1220
1369
|
//Setzen alle Status für Config
|
|
1221
|
-
async setConfigStatus(
|
|
1370
|
+
async setConfigStatus(
|
|
1371
|
+
charger: Charger,
|
|
1372
|
+
charger_config: ChargerConfig,
|
|
1373
|
+
charger_site: Site | null | undefined,
|
|
1374
|
+
): Promise<void> {
|
|
1222
1375
|
await this.setStateAsync(`${charger.id}.config.isEnabled`, {
|
|
1223
1376
|
val: charger_config.isEnabled,
|
|
1224
1377
|
ack: true,
|
|
@@ -1301,7 +1454,7 @@ class Easee extends utils.Adapter {
|
|
|
1301
1454
|
**************************************************************************/
|
|
1302
1455
|
|
|
1303
1456
|
//Get Token from API
|
|
1304
|
-
async login(username, password) {
|
|
1457
|
+
async login(username: string, password: string): Promise<boolean> {
|
|
1305
1458
|
try {
|
|
1306
1459
|
const response = await axios.post(
|
|
1307
1460
|
`${apiUrl}/api/accounts/login`,
|
|
@@ -1339,7 +1492,7 @@ class Easee extends utils.Adapter {
|
|
|
1339
1492
|
}
|
|
1340
1493
|
|
|
1341
1494
|
//GET net Token from API
|
|
1342
|
-
async refreshToken() {
|
|
1495
|
+
async refreshToken(): Promise<void> {
|
|
1343
1496
|
return await axios
|
|
1344
1497
|
.post(
|
|
1345
1498
|
`${apiUrl}/api/accounts/refresh_token`,
|
|
@@ -1373,9 +1526,9 @@ class Easee extends utils.Adapter {
|
|
|
1373
1526
|
}
|
|
1374
1527
|
|
|
1375
1528
|
//Lese alle Charger aus
|
|
1376
|
-
async getAllCharger() {
|
|
1529
|
+
async getAllCharger(): Promise<Charger[] | undefined> {
|
|
1377
1530
|
return await axios
|
|
1378
|
-
.get(`${apiUrl}/api/chargers`, {
|
|
1531
|
+
.get<Charger[]>(`${apiUrl}/api/chargers`, {
|
|
1379
1532
|
headers: { Authorization: `Bearer ${accessToken}` },
|
|
1380
1533
|
timeout: apiRequestTimeout,
|
|
1381
1534
|
})
|
|
@@ -1386,11 +1539,12 @@ class Easee extends utils.Adapter {
|
|
|
1386
1539
|
})
|
|
1387
1540
|
.catch((error) => {
|
|
1388
1541
|
this.log.error(error);
|
|
1542
|
+
return undefined;
|
|
1389
1543
|
});
|
|
1390
1544
|
}
|
|
1391
1545
|
|
|
1392
1546
|
// Lese den Charger aus
|
|
1393
|
-
async getChargerState(charger_id) {
|
|
1547
|
+
async getChargerState(charger_id: string): Promise<ChargerObservationState> {
|
|
1394
1548
|
const response = await this.requestWithBackoff(
|
|
1395
1549
|
`charger observations ${charger_id}`,
|
|
1396
1550
|
() =>
|
|
@@ -1405,7 +1559,7 @@ class Easee extends utils.Adapter {
|
|
|
1405
1559
|
return observationsToChargerState(response.data);
|
|
1406
1560
|
}
|
|
1407
1561
|
|
|
1408
|
-
async getChargerConfig(charger_id) {
|
|
1562
|
+
async getChargerConfig(charger_id: string): Promise<ChargerConfig> {
|
|
1409
1563
|
const response = await this.requestWithBackoff(
|
|
1410
1564
|
`charger config ${charger_id}`,
|
|
1411
1565
|
() =>
|
|
@@ -1419,7 +1573,7 @@ class Easee extends utils.Adapter {
|
|
|
1419
1573
|
return response.data;
|
|
1420
1574
|
}
|
|
1421
1575
|
|
|
1422
|
-
async getChargerSite(charger_id) {
|
|
1576
|
+
async getChargerSite(charger_id: string): Promise<Site> {
|
|
1423
1577
|
const response = await this.requestWithBackoff(
|
|
1424
1578
|
`charger site ${charger_id}`,
|
|
1425
1579
|
() =>
|
|
@@ -1433,7 +1587,10 @@ class Easee extends utils.Adapter {
|
|
|
1433
1587
|
return response.data;
|
|
1434
1588
|
}
|
|
1435
1589
|
|
|
1436
|
-
async getChargerSession(
|
|
1590
|
+
async getChargerSession(
|
|
1591
|
+
charger_id: string,
|
|
1592
|
+
signal?: AbortSignal,
|
|
1593
|
+
): Promise<ChargerSession[]> {
|
|
1437
1594
|
const response = await this.requestWithBackoff(
|
|
1438
1595
|
`charger session ${charger_id}`,
|
|
1439
1596
|
() =>
|
|
@@ -1448,7 +1605,12 @@ class Easee extends utils.Adapter {
|
|
|
1448
1605
|
return response.data;
|
|
1449
1606
|
}
|
|
1450
1607
|
|
|
1451
|
-
async changeChargingPrice(
|
|
1608
|
+
async changeChargingPrice(
|
|
1609
|
+
charger_id: string,
|
|
1610
|
+
site: Site,
|
|
1611
|
+
netPrice: number,
|
|
1612
|
+
vat: number,
|
|
1613
|
+
): Promise<void> {
|
|
1452
1614
|
if (!site || site.id === undefined) {
|
|
1453
1615
|
throw new Error(`No site data available for charger ${charger_id}`);
|
|
1454
1616
|
}
|
|
@@ -1494,7 +1656,7 @@ class Easee extends utils.Adapter {
|
|
|
1494
1656
|
this.log.info("Charging price update successful");
|
|
1495
1657
|
}
|
|
1496
1658
|
|
|
1497
|
-
async startCharging(id) {
|
|
1659
|
+
async startCharging(id: string): Promise<void> {
|
|
1498
1660
|
return await axios
|
|
1499
1661
|
.post(
|
|
1500
1662
|
`${apiUrl}/api/chargers/${id}/commands/start_charging`,
|
|
@@ -1511,7 +1673,7 @@ class Easee extends utils.Adapter {
|
|
|
1511
1673
|
});
|
|
1512
1674
|
}
|
|
1513
1675
|
|
|
1514
|
-
async stopCharging(id) {
|
|
1676
|
+
async stopCharging(id: string): Promise<void> {
|
|
1515
1677
|
return await axios
|
|
1516
1678
|
.post(
|
|
1517
1679
|
`${apiUrl}/api/chargers/${id}/commands/stop_charging`,
|
|
@@ -1528,7 +1690,7 @@ class Easee extends utils.Adapter {
|
|
|
1528
1690
|
});
|
|
1529
1691
|
}
|
|
1530
1692
|
|
|
1531
|
-
async pauseCharging(id) {
|
|
1693
|
+
async pauseCharging(id: string): Promise<void> {
|
|
1532
1694
|
return await axios
|
|
1533
1695
|
.post(
|
|
1534
1696
|
`${apiUrl}/api/chargers/${id}/commands/pause_charging`,
|
|
@@ -1545,7 +1707,7 @@ class Easee extends utils.Adapter {
|
|
|
1545
1707
|
});
|
|
1546
1708
|
}
|
|
1547
1709
|
|
|
1548
|
-
async resumeCharging(id) {
|
|
1710
|
+
async resumeCharging(id: string): Promise<void> {
|
|
1549
1711
|
return await axios
|
|
1550
1712
|
.post(
|
|
1551
1713
|
`${apiUrl}/api/chargers/${id}/commands/resume_charging`,
|
|
@@ -1562,7 +1724,7 @@ class Easee extends utils.Adapter {
|
|
|
1562
1724
|
});
|
|
1563
1725
|
}
|
|
1564
1726
|
|
|
1565
|
-
async rebootCharging(id) {
|
|
1727
|
+
async rebootCharging(id: string): Promise<void> {
|
|
1566
1728
|
return await axios
|
|
1567
1729
|
.post(
|
|
1568
1730
|
`${apiUrl}/api/chargers/${id}/commands/reboot`,
|
|
@@ -1579,7 +1741,11 @@ class Easee extends utils.Adapter {
|
|
|
1579
1741
|
});
|
|
1580
1742
|
}
|
|
1581
1743
|
|
|
1582
|
-
async changeConfig(
|
|
1744
|
+
async changeConfig(
|
|
1745
|
+
id: string,
|
|
1746
|
+
configvalue: string,
|
|
1747
|
+
value: ioBroker.StateValue,
|
|
1748
|
+
): Promise<void> {
|
|
1583
1749
|
this.log.debug(
|
|
1584
1750
|
JSON.stringify({
|
|
1585
1751
|
[configvalue]: value,
|
|
@@ -1604,7 +1770,11 @@ class Easee extends utils.Adapter {
|
|
|
1604
1770
|
}
|
|
1605
1771
|
|
|
1606
1772
|
//circuitMaxCurrentPX
|
|
1607
|
-
async changeMaxCircuitConfig(
|
|
1773
|
+
async changeMaxCircuitConfig(
|
|
1774
|
+
site_id: string,
|
|
1775
|
+
circuit_id: string,
|
|
1776
|
+
value: ioBroker.StateValue,
|
|
1777
|
+
): Promise<void> {
|
|
1608
1778
|
return await axios
|
|
1609
1779
|
.post(
|
|
1610
1780
|
`${apiUrl}/api/sites/${site_id}/circuits/${circuit_id}/settings`,
|
|
@@ -1626,7 +1796,11 @@ class Easee extends utils.Adapter {
|
|
|
1626
1796
|
}
|
|
1627
1797
|
|
|
1628
1798
|
//dynamicCircuitCurrentPX
|
|
1629
|
-
async changeCircuitConfig(
|
|
1799
|
+
async changeCircuitConfig(
|
|
1800
|
+
site_id: string,
|
|
1801
|
+
circuit_id: string,
|
|
1802
|
+
currentValues: ChargerValueSet,
|
|
1803
|
+
): Promise<void> {
|
|
1630
1804
|
//Der Wert darf nur für 3 Fach Werte aktualisiert werden
|
|
1631
1805
|
await axios
|
|
1632
1806
|
.post(
|
|
@@ -1656,7 +1830,7 @@ class Easee extends utils.Adapter {
|
|
|
1656
1830
|
* Funktionen zum erstellen der Objekte der Reading
|
|
1657
1831
|
***********************************************************************/
|
|
1658
1832
|
|
|
1659
|
-
async setAllStatusObjects(charger) {
|
|
1833
|
+
async setAllStatusObjects(charger: Charger): Promise<void> {
|
|
1660
1834
|
//Legen die Steuerungsbutton für jeden Charger an
|
|
1661
1835
|
await this.setObjectNotExistsAsync(`${charger.id}.control.start`, {
|
|
1662
1836
|
type: "state",
|
|
@@ -2145,7 +2319,10 @@ class Easee extends utils.Adapter {
|
|
|
2145
2319
|
}
|
|
2146
2320
|
|
|
2147
2321
|
/*************** Session Reading ****************/
|
|
2148
|
-
async setNewSessionToCharger(
|
|
2322
|
+
async setNewSessionToCharger(
|
|
2323
|
+
charger: Pick<Charger, "id">,
|
|
2324
|
+
charger_session: ChargerSession[],
|
|
2325
|
+
): Promise<void> {
|
|
2149
2326
|
this.log.debug(JSON.stringify(charger_session));
|
|
2150
2327
|
for (const session of charger_session) {
|
|
2151
2328
|
//für jeden Monat errechnen wir das?
|
|
@@ -2235,7 +2412,7 @@ class Easee extends utils.Adapter {
|
|
|
2235
2412
|
}
|
|
2236
2413
|
|
|
2237
2414
|
/*************** Config Reading ****************/
|
|
2238
|
-
async setAllConfigObjects(charger) {
|
|
2415
|
+
async setAllConfigObjects(charger: Charger): Promise<void> {
|
|
2239
2416
|
await this.setObjectNotExistsAsync(`${charger.id}.config.costPerKWh`, {
|
|
2240
2417
|
type: "state",
|
|
2241
2418
|
common: {
|
|
@@ -2508,11 +2685,13 @@ class Easee extends utils.Adapter {
|
|
|
2508
2685
|
}
|
|
2509
2686
|
}
|
|
2510
2687
|
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2688
|
+
const createAdapter = Object.assign(
|
|
2689
|
+
(options: AdapterOptions = { name: "easee" }) => new Easee(options),
|
|
2690
|
+
{ Easee },
|
|
2691
|
+
);
|
|
2692
|
+
|
|
2693
|
+
if (require.main === module) {
|
|
2517
2694
|
new Easee();
|
|
2518
2695
|
}
|
|
2696
|
+
|
|
2697
|
+
export = createAdapter;
|