chore: switch coding style to JS standard
[e-mobility-charging-stations-simulator.git] / src / charging-station / AutomaticTransactionGenerator.ts
CommitLineData
edd13439 1// Partial Copyright Jerome Benoit. 2021-2023. All Rights Reserved.
c8eeb62b 2
66a7748d 3import { hoursToMilliseconds, secondsToMilliseconds } from 'date-fns'
be4c6702 4
66a7748d
JB
5import type { ChargingStation } from './ChargingStation.js'
6import { checkChargingStation } from './Helpers.js'
7import { IdTagsCache } from './IdTagsCache.js'
8import { isIdTagAuthorized } from './ocpp/index.js'
9import { BaseError } from '../exception/index.js'
10import { PerformanceStatistics } from '../performance/index.js'
e7aeea18
JB
11import {
12 AuthorizationStatus,
268a74bb 13 RequestCommand,
976d11ec
JB
14 type StartTransactionRequest,
15 type StartTransactionResponse,
268a74bb 16 type Status,
e7aeea18 17 StopTransactionReason,
66a7748d
JB
18 type StopTransactionResponse
19} from '../types/index.js'
9bf0ef23
JB
20import {
21 Constants,
22 cloneObject,
23 formatDurationMilliSeconds,
24 getRandomInteger,
25 isNullOrUndefined,
26 logPrefix,
27 logger,
28 secureRandom,
66a7748d
JB
29 sleep
30} from '../utils/index.js'
6af9012e 31
d1ff8599 32export class AutomaticTransactionGenerator {
e7aeea18 33 private static readonly instances: Map<string, AutomaticTransactionGenerator> = new Map<
66a7748d
JB
34 string,
35 AutomaticTransactionGenerator
36 >()
10068088 37
66a7748d
JB
38 public readonly connectorsStatus: Map<number, Status>
39 public started: boolean
40 private starting: boolean
41 private stopping: boolean
42 private readonly chargingStation: ChargingStation
6af9012e 43
66a7748d
JB
44 private constructor (chargingStation: ChargingStation) {
45 this.started = false
46 this.starting = false
47 this.stopping = false
48 this.chargingStation = chargingStation
49 this.connectorsStatus = new Map<number, Status>()
50 this.initializeConnectorsStatus()
6af9012e
JB
51 }
52
66a7748d
JB
53 public static getInstance (
54 chargingStation: ChargingStation
1895299d 55 ): AutomaticTransactionGenerator | undefined {
66a7748d 56 if (!AutomaticTransactionGenerator.instances.has(chargingStation.stationInfo.hashId)) {
e7aeea18 57 AutomaticTransactionGenerator.instances.set(
51c83d6f 58 chargingStation.stationInfo.hashId,
66a7748d
JB
59 new AutomaticTransactionGenerator(chargingStation)
60 )
73b9adec 61 }
66a7748d 62 return AutomaticTransactionGenerator.instances.get(chargingStation.stationInfo.hashId)
73b9adec
JB
63 }
64
66a7748d
JB
65 public start (): void {
66 if (!checkChargingStation(this.chargingStation, this.logPrefix())) {
67 return
d1c6c833 68 }
66a7748d
JB
69 if (this.started) {
70 logger.warn(`${this.logPrefix()} is already started`)
71 return
b809adf1 72 }
66a7748d
JB
73 if (this.starting) {
74 logger.warn(`${this.logPrefix()} is already starting`)
75 return
11353865 76 }
66a7748d
JB
77 this.starting = true
78 this.startConnectors()
79 this.started = true
80 this.starting = false
6af9012e
JB
81 }
82
66a7748d
JB
83 public stop (): void {
84 if (!this.started) {
85 logger.warn(`${this.logPrefix()} is already stopped`)
86 return
265e4266 87 }
66a7748d
JB
88 if (this.stopping) {
89 logger.warn(`${this.logPrefix()} is already stopping`)
90 return
11353865 91 }
66a7748d
JB
92 this.stopping = true
93 this.stopConnectors()
94 this.started = false
95 this.stopping = false
6af9012e
JB
96 }
97
66a7748d
JB
98 public startConnector (connectorId: number): void {
99 if (!checkChargingStation(this.chargingStation, this.logPrefix(connectorId))) {
100 return
d1c6c833 101 }
66a7748d
JB
102 if (!this.connectorsStatus.has(connectorId)) {
103 logger.error(`${this.logPrefix(connectorId)} starting on non existing connector`)
104 throw new BaseError(`Connector ${connectorId} does not exist`)
a5e9befc
JB
105 }
106 if (this.connectorsStatus.get(connectorId)?.start === false) {
66a7748d 107 this.internalStartConnector(connectorId).catch(Constants.EMPTY_FUNCTION)
ecb3869d 108 } else if (this.connectorsStatus.get(connectorId)?.start === true) {
66a7748d 109 logger.warn(`${this.logPrefix(connectorId)} is already started on connector`)
a5e9befc
JB
110 }
111 }
112
66a7748d
JB
113 public stopConnector (connectorId: number): void {
114 if (!this.connectorsStatus.has(connectorId)) {
115 logger.error(`${this.logPrefix(connectorId)} stopping on non existing connector`)
116 throw new BaseError(`Connector ${connectorId} does not exist`)
ba7965c4
JB
117 }
118 if (this.connectorsStatus.get(connectorId)?.start === true) {
66a7748d
JB
119 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
120 this.connectorsStatus.get(connectorId)!.start = false
ba7965c4 121 } else if (this.connectorsStatus.get(connectorId)?.start === false) {
66a7748d 122 logger.warn(`${this.logPrefix(connectorId)} is already stopped on connector`)
ba7965c4 123 }
a5e9befc
JB
124 }
125
66a7748d 126 private startConnectors (): void {
e7aeea18
JB
127 if (
128 this.connectorsStatus?.size > 0 &&
129 this.connectorsStatus.size !== this.chargingStation.getNumberOfConnectors()
130 ) {
66a7748d
JB
131 this.connectorsStatus.clear()
132 this.initializeConnectorsStatus()
54544ef1 133 }
4334db72
JB
134 if (this.chargingStation.hasEvses) {
135 for (const [evseId, evseStatus] of this.chargingStation.evses) {
136 if (evseId > 0) {
137 for (const connectorId of evseStatus.connectors.keys()) {
66a7748d 138 this.startConnector(connectorId)
4334db72
JB
139 }
140 }
141 }
142 } else {
143 for (const connectorId of this.chargingStation.connectors.keys()) {
144 if (connectorId > 0) {
66a7748d 145 this.startConnector(connectorId)
4334db72 146 }
72740232
JB
147 }
148 }
149 }
150
66a7748d 151 private stopConnectors (): void {
4334db72
JB
152 if (this.chargingStation.hasEvses) {
153 for (const [evseId, evseStatus] of this.chargingStation.evses) {
154 if (evseId > 0) {
155 for (const connectorId of evseStatus.connectors.keys()) {
66a7748d 156 this.stopConnector(connectorId)
4334db72
JB
157 }
158 }
159 }
160 } else {
161 for (const connectorId of this.chargingStation.connectors.keys()) {
162 if (connectorId > 0) {
66a7748d 163 this.stopConnector(connectorId)
4334db72 164 }
72740232
JB
165 }
166 }
167 }
168
66a7748d
JB
169 private async internalStartConnector (connectorId: number): Promise<void> {
170 this.setStartConnectorStatus(connectorId)
e7aeea18 171 logger.info(
44eb6026 172 `${this.logPrefix(
66a7748d 173 connectorId
9bf0ef23 174 )} started on connector and will run for ${formatDurationMilliSeconds(
66a7748d 175 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
e1d9a0f4 176 this.connectorsStatus.get(connectorId)!.stopDate!.getTime() -
66a7748d
JB
177 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
178 this.connectorsStatus.get(connectorId)!.startDate!.getTime()
179 )}`
180 )
1895299d 181 while (this.connectorsStatus.get(connectorId)?.start === true) {
66a7748d
JB
182 await this.waitChargingStationServiceInitialization(connectorId)
183 await this.waitChargingStationAvailable(connectorId)
184 await this.waitConnectorAvailable(connectorId)
0bd926c1 185 if (!this.canStartConnector(connectorId)) {
66a7748d
JB
186 this.stopConnector(connectorId)
187 break
9b4d0c70 188 }
be4c6702 189 const wait = secondsToMilliseconds(
9bf0ef23 190 getRandomInteger(
ac7f79af 191 this.chargingStation.getAutomaticTransactionGeneratorConfiguration()
86b46b49 192 .maxDelayBetweenTwoTransactions,
ac7f79af 193 this.chargingStation.getAutomaticTransactionGeneratorConfiguration()
66a7748d
JB
194 .minDelayBetweenTwoTransactions
195 )
196 )
197 logger.info(`${this.logPrefix(connectorId)} waiting for ${formatDurationMilliSeconds(wait)}`)
198 await sleep(wait)
199 const start = secureRandom()
ac7f79af
JB
200 if (
201 start <
202 this.chargingStation.getAutomaticTransactionGeneratorConfiguration().probabilityOfStart
203 ) {
66a7748d
JB
204 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
205 this.connectorsStatus.get(connectorId)!.skippedConsecutiveTransactions = 0
6af9012e 206 // Start transaction
66a7748d 207 const startResponse = await this.startTransaction(connectorId)
0afed85f 208 if (startResponse?.idTagInfo?.status === AuthorizationStatus.ACCEPTED) {
6af9012e 209 // Wait until end of transaction
be4c6702 210 const waitTrxEnd = secondsToMilliseconds(
9bf0ef23 211 getRandomInteger(
86b46b49 212 this.chargingStation.getAutomaticTransactionGeneratorConfiguration().maxDuration,
66a7748d
JB
213 this.chargingStation.getAutomaticTransactionGeneratorConfiguration().minDuration
214 )
215 )
e7aeea18 216 logger.info(
1c9de2b9 217 `${this.logPrefix(
66a7748d 218 connectorId
1c9de2b9 219 )} transaction started with id ${this.chargingStation.getConnectorStatus(connectorId)
66a7748d
JB
220 ?.transactionId} and will stop in ${formatDurationMilliSeconds(waitTrxEnd)}`
221 )
222 await sleep(waitTrxEnd)
223 await this.stopTransaction(connectorId)
6af9012e
JB
224 }
225 } else {
66a7748d
JB
226 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
227 ++this.connectorsStatus.get(connectorId)!.skippedConsecutiveTransactions!
228 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
229 ++this.connectorsStatus.get(connectorId)!.skippedTransactions!
e7aeea18 230 logger.info(
1c9de2b9 231 `${this.logPrefix(connectorId)} skipped consecutively ${this.connectorsStatus.get(
66a7748d 232 connectorId
1c9de2b9 233 )?.skippedConsecutiveTransactions}/${this.connectorsStatus.get(connectorId)
66a7748d
JB
234 ?.skippedTransactions} transaction(s)`
235 )
6af9012e 236 }
66a7748d
JB
237 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
238 this.connectorsStatus.get(connectorId)!.lastRunDate = new Date()
7d75bee1 239 }
66a7748d
JB
240 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
241 this.connectorsStatus.get(connectorId)!.stoppedDate = new Date()
e7aeea18 242 logger.info(
44eb6026 243 `${this.logPrefix(
66a7748d 244 connectorId
9bf0ef23 245 )} stopped on connector and lasted for ${formatDurationMilliSeconds(
66a7748d 246 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
e1d9a0f4 247 this.connectorsStatus.get(connectorId)!.stoppedDate!.getTime() -
66a7748d
JB
248 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
249 this.connectorsStatus.get(connectorId)!.startDate!.getTime()
250 )}`
251 )
e7aeea18 252 logger.debug(
be9ee554 253 `${this.logPrefix(connectorId)} connector status: %j`,
66a7748d
JB
254 this.connectorsStatus.get(connectorId)
255 )
6af9012e
JB
256 }
257
66a7748d
JB
258 private setStartConnectorStatus (connectorId: number): void {
259 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
260 this.connectorsStatus.get(connectorId)!.skippedConsecutiveTransactions = 0
e7aeea18 261 const previousRunDuration =
66a7748d
JB
262 this.connectorsStatus.get(connectorId)?.startDate != null &&
263 this.connectorsStatus.get(connectorId)?.lastRunDate != null
264 ? // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
265 this.connectorsStatus.get(connectorId)!.lastRunDate!.getTime() -
266 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
e1d9a0f4 267 this.connectorsStatus.get(connectorId)!.startDate!.getTime()
66a7748d
JB
268 : 0
269 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
270 this.connectorsStatus.get(connectorId)!.startDate = new Date()
271 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
e1d9a0f4 272 this.connectorsStatus.get(connectorId)!.stopDate = new Date(
66a7748d 273 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
e1d9a0f4 274 this.connectorsStatus.get(connectorId)!.startDate!.getTime() +
be4c6702 275 hoursToMilliseconds(
66a7748d 276 this.chargingStation.getAutomaticTransactionGeneratorConfiguration().stopAfterHours
be4c6702 277 ) -
66a7748d
JB
278 previousRunDuration
279 )
280 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
281 this.connectorsStatus.get(connectorId)!.start = true
4dff3039
JB
282 }
283
66a7748d
JB
284 private canStartConnector (connectorId: number): boolean {
285 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
0bd926c1 286 if (new Date() > this.connectorsStatus.get(connectorId)!.stopDate!) {
66a7748d 287 return false
0bd926c1 288 }
66a7748d 289 if (!this.chargingStation.inAcceptedState()) {
0bd926c1
JB
290 logger.error(
291 `${this.logPrefix(
66a7748d
JB
292 connectorId
293 )} entered in transaction loop while the charging station is not in accepted state`
294 )
295 return false
0bd926c1 296 }
66a7748d 297 if (!this.chargingStation.isChargingStationAvailable()) {
0bd926c1
JB
298 logger.info(
299 `${this.logPrefix(
66a7748d
JB
300 connectorId
301 )} entered in transaction loop while the charging station is unavailable`
302 )
303 return false
0bd926c1 304 }
66a7748d 305 if (!this.chargingStation.isConnectorAvailable(connectorId)) {
0bd926c1
JB
306 logger.info(
307 `${this.logPrefix(
66a7748d
JB
308 connectorId
309 )} entered in transaction loop while the connector ${connectorId} is unavailable`
310 )
311 return false
0bd926c1 312 }
66a7748d 313 return true
0bd926c1
JB
314 }
315
66a7748d
JB
316 private async waitChargingStationServiceInitialization (connectorId: number): Promise<void> {
317 let logged = false
318 while (this.chargingStation?.ocppRequestService == null) {
60400e23
JB
319 if (!logged) {
320 logger.info(
321 `${this.logPrefix(
66a7748d
JB
322 connectorId
323 )} transaction loop waiting for charging station service to be initialized`
324 )
325 logged = true
60400e23 326 }
66a7748d 327 await sleep(Constants.CHARGING_STATION_ATG_INITIALIZATION_TIME)
3e888c65
JB
328 }
329 }
330
66a7748d
JB
331 private async waitChargingStationAvailable (connectorId: number): Promise<void> {
332 let logged = false
60400e23
JB
333 while (!this.chargingStation.isChargingStationAvailable()) {
334 if (!logged) {
335 logger.info(
336 `${this.logPrefix(
66a7748d
JB
337 connectorId
338 )} transaction loop waiting for charging station to be available`
339 )
340 logged = true
60400e23 341 }
66a7748d 342 await sleep(Constants.CHARGING_STATION_ATG_AVAILABILITY_TIME)
3e888c65
JB
343 }
344 }
345
66a7748d
JB
346 private async waitConnectorAvailable (connectorId: number): Promise<void> {
347 let logged = false
60400e23
JB
348 while (!this.chargingStation.isConnectorAvailable(connectorId)) {
349 if (!logged) {
350 logger.info(
351 `${this.logPrefix(
66a7748d
JB
352 connectorId
353 )} transaction loop waiting for connector ${connectorId} to be available`
354 )
355 logged = true
60400e23 356 }
66a7748d 357 await sleep(Constants.CHARGING_STATION_ATG_AVAILABILITY_TIME)
3e888c65
JB
358 }
359 }
360
66a7748d 361 private initializeConnectorsStatus (): void {
4334db72
JB
362 if (this.chargingStation.hasEvses) {
363 for (const [evseId, evseStatus] of this.chargingStation.evses) {
364 if (evseId > 0) {
365 for (const connectorId of evseStatus.connectors.keys()) {
66a7748d 366 this.connectorsStatus.set(connectorId, this.getConnectorStatus(connectorId))
4334db72
JB
367 }
368 }
369 }
370 } else {
371 for (const connectorId of this.chargingStation.connectors.keys()) {
372 if (connectorId > 0) {
66a7748d 373 this.connectorsStatus.set(connectorId, this.getConnectorStatus(connectorId))
4334db72 374 }
4dff3039
JB
375 }
376 }
72740232
JB
377 }
378
66a7748d
JB
379 private getConnectorStatus (connectorId: number): Status {
380 const connectorStatus =
381 this.chargingStation.getAutomaticTransactionGeneratorStatuses()?.[connectorId] != null
382 ? cloneObject<Status>(
383 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
384 this.chargingStation.getAutomaticTransactionGeneratorStatuses()![connectorId]
a82d0329 385 )
66a7748d
JB
386 : undefined
387 this.resetConnectorStatus(connectorStatus)
5ced7e80
JB
388 return (
389 connectorStatus ?? {
390 start: false,
391 authorizeRequests: 0,
392 acceptedAuthorizeRequests: 0,
393 rejectedAuthorizeRequests: 0,
394 startTransactionRequests: 0,
395 acceptedStartTransactionRequests: 0,
396 rejectedStartTransactionRequests: 0,
397 stopTransactionRequests: 0,
398 acceptedStopTransactionRequests: 0,
399 rejectedStopTransactionRequests: 0,
400 skippedConsecutiveTransactions: 0,
66a7748d 401 skippedTransactions: 0
5ced7e80 402 }
66a7748d 403 )
5ced7e80
JB
404 }
405
66a7748d 406 private resetConnectorStatus (connectorStatus: Status | undefined): void {
37e207d1 407 if (connectorStatus === undefined) {
66a7748d 408 return
37e207d1 409 }
66a7748d
JB
410 delete connectorStatus?.startDate
411 delete connectorStatus?.lastRunDate
412 delete connectorStatus?.stopDate
413 delete connectorStatus?.stoppedDate
3d20f4db
JB
414 if (
415 !this.started &&
66a7748d
JB
416 (connectorStatus.start ||
417 !this.chargingStation.getAutomaticTransactionGeneratorConfiguration().enable)
3d20f4db 418 ) {
66a7748d 419 connectorStatus.start = false
3d20f4db
JB
420 }
421 }
422
66a7748d
JB
423 private async startTransaction (
424 connectorId: number
0afed85f 425 ): Promise<StartTransactionResponse | undefined> {
66a7748d
JB
426 const measureId = 'StartTransaction with ATG'
427 const beginId = PerformanceStatistics.beginMeasure(measureId)
428 let startResponse: StartTransactionResponse | undefined
f911a4af
JB
429 if (this.chargingStation.hasIdTags()) {
430 const idTag = IdTagsCache.getInstance().getIdTag(
66a7748d 431 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
e1d9a0f4 432 this.chargingStation.getAutomaticTransactionGeneratorConfiguration().idTagDistribution!,
aaf2bf9c 433 this.chargingStation,
66a7748d
JB
434 connectorId
435 )
5cf9050d 436 const startTransactionLogMsg = `${this.logPrefix(
66a7748d
JB
437 connectorId
438 )} start transaction with an idTag '${idTag}'`
ccb1d6e9 439 if (this.getRequireAuthorize()) {
66a7748d
JB
440 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
441 ++this.connectorsStatus.get(connectorId)!.authorizeRequests!
041365be 442 if (await isIdTagAuthorized(this.chargingStation, connectorId, idTag)) {
66a7748d
JB
443 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
444 ++this.connectorsStatus.get(connectorId)!.acceptedAuthorizeRequests!
445 logger.info(startTransactionLogMsg)
5fdab605 446 // Start transaction
f7f98c68 447 startResponse = await this.chargingStation.ocppRequestService.requestHandler<
66a7748d
JB
448 StartTransactionRequest,
449 StartTransactionResponse
08f130a0 450 >(this.chargingStation, RequestCommand.START_TRANSACTION, {
ef6fa3fb 451 connectorId,
66a7748d
JB
452 idTag
453 })
454 this.handleStartTransactionResponse(connectorId, startResponse)
455 PerformanceStatistics.endMeasure(measureId, beginId)
456 return startResponse
5fdab605 457 }
66a7748d
JB
458 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
459 ++this.connectorsStatus.get(connectorId)!.rejectedAuthorizeRequests!
460 PerformanceStatistics.endMeasure(measureId, beginId)
461 return startResponse
ef6076c1 462 }
66a7748d 463 logger.info(startTransactionLogMsg)
5fdab605 464 // Start transaction
f7f98c68 465 startResponse = await this.chargingStation.ocppRequestService.requestHandler<
66a7748d
JB
466 StartTransactionRequest,
467 StartTransactionResponse
08f130a0 468 >(this.chargingStation, RequestCommand.START_TRANSACTION, {
ef6fa3fb 469 connectorId,
66a7748d
JB
470 idTag
471 })
472 this.handleStartTransactionResponse(connectorId, startResponse)
473 PerformanceStatistics.endMeasure(measureId, beginId)
474 return startResponse
6af9012e 475 }
66a7748d 476 logger.info(`${this.logPrefix(connectorId)} start transaction without an idTag`)
f7f98c68 477 startResponse = await this.chargingStation.ocppRequestService.requestHandler<
66a7748d
JB
478 StartTransactionRequest,
479 StartTransactionResponse
480 >(this.chargingStation, RequestCommand.START_TRANSACTION, { connectorId })
481 this.handleStartTransactionResponse(connectorId, startResponse)
482 PerformanceStatistics.endMeasure(measureId, beginId)
483 return startResponse
6af9012e
JB
484 }
485
66a7748d 486 private async stopTransaction (
e7aeea18 487 connectorId: number,
66a7748d 488 reason = StopTransactionReason.LOCAL
e1d9a0f4 489 ): Promise<StopTransactionResponse | undefined> {
66a7748d
JB
490 const measureId = 'StopTransaction with ATG'
491 const beginId = PerformanceStatistics.beginMeasure(measureId)
492 let stopResponse: StopTransactionResponse | undefined
6d9876e7 493 if (this.chargingStation.getConnectorStatus(connectorId)?.transactionStarted === true) {
49563992
JB
494 logger.info(
495 `${this.logPrefix(
66a7748d 496 connectorId
49563992 497 )} stop transaction with id ${this.chargingStation.getConnectorStatus(connectorId)
66a7748d
JB
498 ?.transactionId}`
499 )
500 stopResponse = await this.chargingStation.stopTransactionOnConnector(connectorId, reason)
501 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
502 ++this.connectorsStatus.get(connectorId)!.stopTransactionRequests!
0afed85f 503 if (stopResponse?.idTagInfo?.status === AuthorizationStatus.ACCEPTED) {
66a7748d
JB
504 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
505 ++this.connectorsStatus.get(connectorId)!.acceptedStopTransactionRequests!
6d9876e7 506 } else {
66a7748d
JB
507 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
508 ++this.connectorsStatus.get(connectorId)!.rejectedStopTransactionRequests!
6d9876e7 509 }
0045cef5 510 } else {
66a7748d 511 const transactionId = this.chargingStation.getConnectorStatus(connectorId)?.transactionId
ff581359 512 logger.debug(
ba7965c4 513 `${this.logPrefix(connectorId)} stopping a not started transaction${
1c9de2b9 514 !isNullOrUndefined(transactionId) ? ` with id ${transactionId}` : ''
66a7748d
JB
515 }`
516 )
0045cef5 517 }
66a7748d
JB
518 PerformanceStatistics.endMeasure(measureId, beginId)
519 return stopResponse
c0560973
JB
520 }
521
66a7748d 522 private getRequireAuthorize (): boolean {
ac7f79af
JB
523 return (
524 this.chargingStation.getAutomaticTransactionGeneratorConfiguration()?.requireAuthorize ?? true
66a7748d 525 )
ccb1d6e9
JB
526 }
527
66a7748d 528 private readonly logPrefix = (connectorId?: number): string => {
9bf0ef23 529 return logPrefix(
6cd85def 530 ` ${this.chargingStation.stationInfo.chargingStationId} | ATG${
1c9de2b9 531 !isNullOrUndefined(connectorId) ? ` on connector #${connectorId}` : ''
66a7748d
JB
532 }:`
533 )
534 }
d9ac47ef 535
66a7748d 536 private handleStartTransactionResponse (
d9ac47ef 537 connectorId: number,
66a7748d 538 startResponse: StartTransactionResponse
d9ac47ef 539 ): void {
66a7748d
JB
540 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
541 ++this.connectorsStatus.get(connectorId)!.startTransactionRequests!
d9ac47ef 542 if (startResponse?.idTagInfo?.status === AuthorizationStatus.ACCEPTED) {
66a7748d
JB
543 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
544 ++this.connectorsStatus.get(connectorId)!.acceptedStartTransactionRequests!
d9ac47ef 545 } else {
66a7748d
JB
546 logger.warn(`${this.logPrefix(connectorId)} start transaction rejected`)
547 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
548 ++this.connectorsStatus.get(connectorId)!.rejectedStartTransactionRequests!
d9ac47ef
JB
549 }
550 }
6af9012e 551}