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