checkChargingStationState,
checkConfiguration,
checkConnectorsConfiguration,
+ checkEvsesConfiguration,
checkStationInfoConnectorStatus,
checkTemplate,
createBootNotificationRequest,
if (stationTemplate.Connectors != null) {
checkConnectorsConfiguration(stationTemplate, this.logPrefix(), this.templateFile)
}
+ if (stationTemplate.Evses != null) {
+ checkEvsesConfiguration(stationTemplate, this.logPrefix(), this.templateFile)
+ }
const stationInfo = stationTemplateToStationInfo(stationTemplate)
stationInfo.hashId = getHashId(this.index, stationTemplate)
stationInfo.templateIndex = this.index
private initializeConnectorsOrEvsesFromFile (configuration: ChargingStationConfiguration): void {
if (configuration.connectorsStatus != null && configuration.evsesStatus == null) {
- for (const [connectorId, connectorStatus] of configuration.connectorsStatus.entries()) {
+ const isTupleFormat =
+ configuration.connectorsStatus.length > 0 &&
+ Array.isArray(configuration.connectorsStatus[0])
+ const entries: [number, ConnectorStatus][] = isTupleFormat
+ ? (configuration.connectorsStatus as [number, ConnectorStatus][])
+ : (configuration.connectorsStatus as ConnectorStatus[]).map((status, index) => [
+ index,
+ status,
+ ])
+ for (const [connectorId, connectorStatus] of entries) {
this.connectors.set(
connectorId,
prepareConnectorStatus(clone<ConnectorStatus>(connectorStatus))
)
}
} else if (configuration.evsesStatus != null && configuration.connectorsStatus == null) {
- for (const [evseId, evseStatusConfiguration] of configuration.evsesStatus.entries()) {
+ const isTupleFormat =
+ configuration.evsesStatus.length > 0 && Array.isArray(configuration.evsesStatus[0])
+ const evseEntries: [number, EvseStatusConfiguration][] = isTupleFormat
+ ? (configuration.evsesStatus as [number, EvseStatusConfiguration][])
+ : (configuration.evsesStatus as EvseStatusConfiguration[]).map((status, index) => [
+ index,
+ status,
+ ])
+ for (const [evseId, evseStatusConfiguration] of evseEntries) {
const evseStatus = clone<EvseStatusConfiguration>(evseStatusConfiguration)
delete evseStatus.connectorsStatus
+ const connIsTupleFormat =
+ evseStatusConfiguration.connectorsStatus != null &&
+ evseStatusConfiguration.connectorsStatus.length > 0 &&
+ Array.isArray(evseStatusConfiguration.connectorsStatus[0])
+ const connEntries: [number, ConnectorStatus][] = connIsTupleFormat
+ ? (evseStatusConfiguration.connectorsStatus as [number, ConnectorStatus][])
+ : ((evseStatusConfiguration.connectorsStatus ?? []) as ConnectorStatus[]).map(
+ (status, index) => [index, status]
+ )
this.evses.set(evseId, {
...(evseStatus as EvseStatus),
connectors: new Map<number, ConnectorStatus>(
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- evseStatusConfiguration.connectorsStatus!.map((connectorStatus, connectorId) => [
+ connEntries.map(([connectorId, connectorStatus]) => [
connectorId,
prepareConnectorStatus(connectorStatus),
])
)
}
-export const buildConnectorsStatus = (chargingStation: ChargingStation): ConnectorStatus[] => {
- return [...chargingStation.connectors.values()].map(
- ({
- transactionEventQueue,
- transactionSetInterval,
- transactionTxUpdatedSetInterval,
- ...connectorStatus
- }) => connectorStatus
+export const buildConnectorsStatus = (
+ chargingStation: ChargingStation
+): [number, ConnectorStatus][] => {
+ return [...chargingStation.connectors.entries()].map(
+ ([
+ connectorId,
+ {
+ transactionEventQueue,
+ transactionSetInterval,
+ transactionTxUpdatedSetInterval,
+ ...connectorStatus
+ },
+ ]) => [connectorId, connectorStatus]
)
}
}))
}
-export const buildEvsesStatus = (chargingStation: ChargingStation): EvseStatusConfiguration[] => {
- return [...chargingStation.evses.values()].map(evseStatus => {
- const connectorsStatus = [...evseStatus.connectors.values()].map(
- ({
- transactionEventQueue,
- transactionSetInterval,
- transactionTxUpdatedSetInterval,
- ...connectorStatus
- }) => connectorStatus
+export const buildEvsesStatus = (
+ chargingStation: ChargingStation
+): [number, EvseStatusConfiguration][] => {
+ return [...chargingStation.evses.entries()].map(([evseId, evseStatus]) => {
+ const connectorsStatus: [number, ConnectorStatus][] = [...evseStatus.connectors.entries()].map(
+ ([
+ connectorId,
+ {
+ transactionEventQueue,
+ transactionSetInterval,
+ transactionTxUpdatedSetInterval,
+ ...connector
+ },
+ ]) => [connectorId, connector]
)
- const status: EvseStatusConfiguration = {
- ...evseStatus,
- connectorsStatus,
- }
- delete (status as { connectors?: unknown }).connectors
- return status
+ const { connectors: _, ...evseStatusRest } = evseStatus
+ return [
+ evseId,
+ {
+ ...evseStatusRest,
+ connectorsStatus,
+ } as EvseStatusConfiguration,
+ ]
})
}
const result = buildConnectorsStatus(station)
assert.strictEqual(result.length, 2)
- for (const connector of result) {
+ for (const [, connector] of result) {
assert.ok(!('transactionSetInterval' in connector))
assert.ok(!('transactionEventQueue' in connector))
assert.ok(!('transactionTxUpdatedSetInterval' in connector))
}
- assert.strictEqual(result[1].availability, AvailabilityType.Operative)
+ assert.strictEqual(result[0][0], 0)
+ assert.strictEqual(result[1][0], 1)
+ assert.strictEqual(result[1][1].availability, AvailabilityType.Operative)
} finally {
clearInterval(interval1)
clearInterval(interval2)
const result = buildConnectorsStatus(station)
assert.strictEqual(result.length, 1)
- assert.strictEqual(result[0].availability, AvailabilityType.Operative)
- assert.strictEqual(result[0].transactionId, 42)
- assert.strictEqual(result[0].transactionStarted, true)
+ assert.strictEqual(result[0][0], 1)
+ assert.strictEqual(result[0][1].availability, AvailabilityType.Operative)
+ assert.strictEqual(result[0][1].transactionId, 42)
+ assert.strictEqual(result[0][1].transactionStarted, true)
+ })
+
+ await it('should preserve non-sequential connector IDs', () => {
+ const connectors = new Map<number, ConnectorStatus>()
+ connectors.set(0, {
+ availability: AvailabilityType.Operative,
+ MeterValues: [],
+ } as ConnectorStatus)
+ connectors.set(3, {
+ availability: AvailabilityType.Inoperative,
+ MeterValues: [],
+ } as ConnectorStatus)
+
+ const station = createMockStationForConfigUtils({ connectors })
+ const result = buildConnectorsStatus(station)
+
+ assert.strictEqual(result.length, 2)
+ assert.strictEqual(result[0][0], 0)
+ assert.strictEqual(result[1][0], 3)
+ assert.strictEqual(result[1][1].availability, AvailabilityType.Inoperative)
})
})
const result = buildEvsesStatus(station)
assert.strictEqual(result.length, 2)
- const evse1 = result[1] as Record<string, unknown>
+ assert.strictEqual(result[1][0], 1)
+ const evse1 = result[1][1]
assert.ok('connectorsStatus' in evse1)
assert.ok(!('connectors' in evse1))
+ const connectorsStatus = evse1.connectorsStatus as [number, ConnectorStatus][]
+ assert.strictEqual(connectorsStatus.length, 1)
+ assert.strictEqual(connectorsStatus[0][0], 1)
})
await it('should strip internal fields from evse connectors', () => {
const station = createMockStationForConfigUtils({ evses })
const result = buildEvsesStatus(station)
- const evse1 = result[0] as Record<string, unknown>
- const connectorsStatus = evse1.connectorsStatus as ConnectorStatus[]
+ const evse1 = result[0][1]
+ const connectorsStatus = evse1.connectorsStatus as [number, ConnectorStatus][]
assert.strictEqual(connectorsStatus.length, 1)
- assert.ok(!('transactionSetInterval' in connectorsStatus[0]))
- assert.ok(!('transactionEventQueue' in connectorsStatus[0]))
- assert.ok(!('transactionTxUpdatedSetInterval' in connectorsStatus[0]))
+ assert.strictEqual(connectorsStatus[0][0], 1)
+ const connector = connectorsStatus[0][1]
+ assert.ok(!('transactionSetInterval' in connector))
+ assert.ok(!('transactionEventQueue' in connector))
+ assert.ok(!('transactionTxUpdatedSetInterval' in connector))
+ })
+
+ await it('should preserve connector IDs across serialization', () => {
+ const evseConnectors = new Map<number, ConnectorStatus>()
+ evseConnectors.set(1, {
+ availability: AvailabilityType.Operative,
+ MeterValues: [],
+ } as ConnectorStatus)
+ evseConnectors.set(2, {
+ availability: AvailabilityType.Inoperative,
+ MeterValues: [],
+ } as ConnectorStatus)
+
+ const evse0Connectors = new Map<number, ConnectorStatus>()
+ evse0Connectors.set(0, {
+ availability: AvailabilityType.Operative,
+ MeterValues: [],
+ } as ConnectorStatus)
+
+ const evses = new Map<number, EvseStatus>()
+ evses.set(0, {
+ availability: AvailabilityType.Operative,
+ connectors: evse0Connectors,
+ })
+ evses.set(1, {
+ availability: AvailabilityType.Operative,
+ connectors: evseConnectors,
+ })
+
+ const station = createMockStationForConfigUtils({ evses })
+ const result = buildEvsesStatus(station)
+
+ const evse0Status = result[0][1].connectorsStatus as [number, ConnectorStatus][]
+ assert.ok(evse0Status.length > 0)
+ assert.strictEqual(evse0Status[0][0], 0)
+
+ const evse1Status = result[1][1].connectorsStatus as [number, ConnectorStatus][]
+ assert.ok(evse1Status.length > 1)
+ assert.strictEqual(evse1Status[0][0], 1)
+ assert.strictEqual(evse1Status[1][0], 2)
+ assert.strictEqual(evse1Status[1][1].availability, AvailabilityType.Inoperative)
})
await it('should handle empty evses map', () => {
const result = buildEvsesStatus(station)
assert.strictEqual(result.length, 0)
})
+
+ await it('should preserve non-sequential evse IDs', () => {
+ const evses = new Map<number, EvseStatus>()
+ evses.set(0, {
+ availability: AvailabilityType.Operative,
+ connectors: new Map<number, ConnectorStatus>(),
+ })
+ evses.set(3, {
+ availability: AvailabilityType.Inoperative,
+ connectors: new Map<number, ConnectorStatus>(),
+ })
+
+ const station = createMockStationForConfigUtils({ evses })
+ const result = buildEvsesStatus(station)
+
+ assert.strictEqual(result.length, 2)
+ assert.strictEqual(result[0][0], 0)
+ assert.strictEqual(result[1][0], 3)
+ assert.strictEqual(result[1][1].availability, AvailabilityType.Inoperative)
+ })
})
await describe('buildChargingStationAutomaticTransactionGeneratorConfiguration', async () => {