import { createHash } from 'node:crypto'
import { EventEmitter } from 'node:events'
import { type FSWatcher, existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs'
-import { dirname, join, parse } from 'node:path'
+import { dirname, join } from 'node:path'
import { URL } from 'node:url'
import { parentPort } from 'node:worker_threads'
import { millisecondsToSeconds, secondsToMilliseconds } from 'date-fns'
-import merge from 'just-merge'
+import { mergeDeepRight } from 'rambda'
import { type RawData, WebSocket } from 'ws'
import { AutomaticTransactionGenerator } from './AutomaticTransactionGenerator.js'
FirmwareStatus,
type FirmwareStatusNotificationRequest,
type FirmwareStatusNotificationResponse,
- type FirmwareUpgrade,
type HeartbeatRequest,
type HeartbeatResponse,
type IncomingRequest,
buildEvsesStatus,
buildStartedMessage,
buildStoppedMessage,
+ buildTemplateName,
buildUpdatedMessage,
clone,
convertToBoolean,
public started: boolean
public starting: boolean
public idTagsCache: IdTagsCache
- public automaticTransactionGenerator!: AutomaticTransactionGenerator | undefined
- public ocppConfiguration!: ChargingStationOcppConfiguration | undefined
+ public automaticTransactionGenerator?: AutomaticTransactionGenerator
+ public ocppConfiguration?: ChargingStationOcppConfiguration
public wsConnection: WebSocket | null
public readonly connectors: Map<number, ConnectorStatus>
public readonly evses: Map<number, EvseStatus>
public readonly requests: Map<string, CachedRequest>
- public performanceStatistics: PerformanceStatistics | undefined
+ public performanceStatistics?: PerformanceStatistics
public heartbeatSetInterval?: NodeJS.Timeout
public ocppRequestService!: OCPPRequestService
public bootNotificationRequest?: BootNotificationRequest
private configuredSupervisionUrl!: URL
private wsConnectionRetried: boolean
private wsConnectionRetryCount: number
- private templateFileWatcher: FSWatcher | undefined
+ private templateFileWatcher?: FSWatcher
private templateFileHash!: string
private readonly sharedLRUCache: SharedLRUCache
private wsPingSetInterval?: NodeJS.Timeout
this.add()
- if (options?.autoStart != null) {
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- this.stationInfo!.autoStart = options.autoStart
- }
-
if (this.stationInfo?.autoStart === true) {
this.start()
}
} else {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.stationInfo!.supervisionUrls = url
- this.saveStationInfo()
this.configuredSupervisionUrl = this.getConfiguredSupervisionUrl()
+ this.saveStationInfo()
}
}
}
const stationInfo = stationTemplateToStationInfo(stationTemplate)
stationInfo.hashId = getHashId(this.index, stationTemplate)
- stationInfo.templateName = parse(this.templateFile).name
+ stationInfo.templateIndex = this.index
+ stationInfo.templateName = buildTemplateName(this.templateFile)
stationInfo.chargingStationId = getChargingStationId(this.index, stationTemplate)
createSerialNumber(stationTemplate, stationInfo)
stationInfo.voltageOut = this.getVoltageOut(stationInfo)
} does not match firmware version pattern '${stationInfo.firmwareVersionPattern}'`
)
}
- stationInfo.firmwareUpgrade = merge<FirmwareUpgrade>(
+ stationInfo.firmwareUpgrade = mergeDeepRight(
{
versionUpgrade: {
step: 1
stationInfo = this.getConfigurationFromFile()?.stationInfo
if (stationInfo != null) {
delete stationInfo.infoHash
+ delete (stationInfo as ChargingStationTemplate).numberOfConnectors
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
+ if (stationInfo.templateIndex == null) {
+ stationInfo.templateIndex = this.index
+ }
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (stationInfo.templateName == null) {
- stationInfo.templateName = parse(this.templateFile).name
+ stationInfo.templateName = buildTemplateName(this.templateFile)
}
}
}
} else {
delete configurationData.configurationKey
}
- configurationData = merge<ChargingStationConfiguration>(
+ configurationData = mergeDeepRight(
configurationData,
buildChargingStationAutomaticTransactionGeneratorConfiguration(this)
)
private async onOpen (): Promise<void> {
if (this.isWebSocketConnectionOpened()) {
+ this.emit(ChargingStationEvents.updated)
logger.info(
`${this.logPrefix()} Connection to OCPP server through ${this.wsConnectionUrl.href} succeeded`
)
private onClose (code: WebSocketCloseEventStatusCode, reason: Buffer): void {
this.emit(ChargingStationEvents.disconnected)
+ this.emit(ChargingStationEvents.updated)
switch (code) {
// Normal close
case WebSocketCloseEventStatusCode.CLOSE_NORMAL:
)}' and reason '${reason.toString()}'`
)
this.started &&
- this.reconnect().catch(error =>
- logger.error(`${this.logPrefix()} Error while reconnecting:`, error)
- )
+ this.reconnect()
+ .then(() => {
+ this.emit(ChargingStationEvents.updated)
+ })
+ .catch(error => logger.error(`${this.logPrefix()} Error while reconnecting:`, error))
break
}
- this.emit(ChargingStationEvents.updated)
}
private getCachedRequest (