delete connectorStatus.transactionSeqNo
delete connectorStatus.transactionEvseSent
delete connectorStatus.transactionIdTokenSent
+ delete connectorStatus.transactionDeauthorized
+ delete connectorStatus.transactionDeauthorizedEnergyWh
}
export const prepareConnectorStatus = (connectorStatus: ConnectorStatus): ConnectorStatus => {
)
return
}
- connectorStatus.transactionSetInterval = setInterval(() => {
+ connectorStatus.transactionMeterValuesSetInterval = setInterval(() => {
const transactionId = convertToInt(connectorStatus.transactionId)
const meterValue = buildMeterValue(chargingStation, connectorId, transactionId, interval)
chargingStation.ocppRequestService
connectorId: number
): void {
const connectorStatus = chargingStation.getConnectorStatus(connectorId)
- if (connectorStatus?.transactionSetInterval != null) {
- clearInterval(connectorStatus.transactionSetInterval)
- delete connectorStatus.transactionSetInterval
+ if (connectorStatus?.transactionMeterValuesSetInterval != null) {
+ clearInterval(connectorStatus.transactionMeterValuesSetInterval)
+ delete connectorStatus.transactionMeterValuesSetInterval
}
}
import {
clampToSafeTimerValue,
Constants,
+ convertToBoolean,
+ convertToInt,
convertToIntOrNaN,
formatDurationMilliSeconds,
generateUUID,
return { bytesLimit, itemsLimit }
}
- // E05.FR.09/FR.10 + E06.FR.04: Updated(Deauthorized) → Ended(DeAuthorized). Assumes StopTxOnInvalidId=true.
public static async requestDeauthorizeTransaction (
chargingStation: ChargingStation,
connectorId: number,
connectorId
)
+ const stopTxOnInvalidId = OCPP20ServiceUtils.readVariableAsBoolean(
+ chargingStation,
+ OCPP20ComponentName.TxCtrlr,
+ OCPP20RequiredVariableName.StopTxOnInvalidId,
+ true
+ )
+
+ if (!stopTxOnInvalidId) {
+ await this.sendTransactionEvent(
+ chargingStation,
+ OCPP20TransactionEventEnumType.Updated,
+ OCPP20TriggerReasonEnumType.Deauthorized,
+ connectorId,
+ transactionId,
+ { evseId }
+ )
+ return { idTokenInfo: undefined }
+ }
+
+ const maxEnergyOnInvalidId = OCPP20ServiceUtils.readVariableAsInteger(
+ chargingStation,
+ OCPP20ComponentName.TxCtrlr,
+ 'MaxEnergyOnInvalidId',
+ 0
+ )
+
+ if (maxEnergyOnInvalidId > 0) {
+ // E05.FR.03: continue charging up to MaxEnergyOnInvalidId Wh before terminating
+ connectorStatus.transactionDeauthorized = true
+ connectorStatus.transactionDeauthorizedEnergyWh =
+ connectorStatus.transactionEnergyActiveImportRegisterValue ?? 0
+
+ await this.sendTransactionEvent(
+ chargingStation,
+ OCPP20TransactionEventEnumType.Updated,
+ OCPP20TriggerReasonEnumType.Deauthorized,
+ connectorId,
+ transactionId,
+ { evseId }
+ )
+
+ return { idTokenInfo: undefined }
+ }
+
await this.sendTransactionEvent(
chargingStation,
OCPP20TransactionEventEnumType.Updated,
)
return
}
- if (connector.transactionTxUpdatedSetInterval != null) {
+ if (connector.transactionMeterValuesSetInterval != null) {
logger.warn(
`${chargingStation.logPrefix()} ${moduleName}.startPeriodicMeterValues: TxUpdatedInterval already started, stopping first`
)
OCPP20ServiceUtils.stopPeriodicMeterValues(chargingStation, connectorId)
}
- connector.transactionTxUpdatedSetInterval = setInterval(() => {
+ connector.transactionMeterValuesSetInterval = setInterval(() => {
const connectorStatus = chargingStation.getConnectorStatus(connectorId)
if (connectorStatus?.transactionStarted === true && connectorStatus.transactionId != null) {
+ if (
+ connectorStatus.transactionDeauthorized === true &&
+ connectorStatus.transactionDeauthorizedEnergyWh != null
+ ) {
+ const maxEnergy = OCPP20ServiceUtils.readVariableAsInteger(
+ chargingStation,
+ OCPP20ComponentName.TxCtrlr,
+ 'MaxEnergyOnInvalidId',
+ 0
+ )
+ const currentEnergy = connectorStatus.transactionEnergyActiveImportRegisterValue ?? 0
+ const energySinceDeauth = currentEnergy - connectorStatus.transactionDeauthorizedEnergyWh
+ if (maxEnergy > 0 && energySinceDeauth >= maxEnergy) {
+ const evseId = chargingStation.getEvseIdByConnectorId(connectorId)
+ OCPP20ServiceUtils.terminateTransaction(
+ chargingStation,
+ connectorId,
+ connectorStatus,
+ connectorStatus.transactionId.toString(),
+ OCPP20TriggerReasonEnumType.Deauthorized,
+ OCPP20ReasonEnumType.DeAuthorized,
+ evseId
+ ).catch((error: unknown) => {
+ logger.error(
+ `${chargingStation.logPrefix()} ${moduleName}.startPeriodicMeterValues: Error terminating deauthorized transaction:`,
+ error
+ )
+ })
+ return
+ }
+ }
const meterValue = buildMeterValue(
chargingStation,
connectorId,
connectorId: number
): void {
const connector = chargingStation.getConnectorStatus(connectorId)
- if (connector?.transactionTxUpdatedSetInterval != null) {
- clearInterval(connector.transactionTxUpdatedSetInterval)
- delete connector.transactionTxUpdatedSetInterval
+ if (connector?.transactionMeterValuesSetInterval != null) {
+ clearInterval(connector.transactionMeterValuesSetInterval)
+ delete connector.transactionMeterValuesSetInterval
logger.info(
`${chargingStation.logPrefix()} ${moduleName}.stopPeriodicMeterValues: TxUpdatedInterval stopped`
)
)
}
+ private static readVariableAsBoolean (
+ chargingStation: ChargingStation,
+ componentName: string,
+ variableName: string,
+ defaultValue: boolean
+ ): boolean {
+ const value = OCPP20ServiceUtils.readVariableValue(chargingStation, componentName, variableName)
+ return value != null ? convertToBoolean(value) : defaultValue
+ }
+
+ private static readVariableAsInteger (
+ chargingStation: ChargingStation,
+ componentName: string,
+ variableName: string,
+ defaultValue: number
+ ): number {
+ const value = OCPP20ServiceUtils.readVariableValue(chargingStation, componentName, variableName)
+ if (value != null) {
+ try {
+ return convertToInt(value)
+ } catch {
+ logger.warn(
+ `${moduleName}.readVariableAsInteger: Cannot convert '${value}' to integer for ${componentName}.${variableName}, using default ${defaultValue.toString()}`
+ )
+ return defaultValue
+ }
+ }
+ return defaultValue
+ }
+
private static readVariableAsIntervalMs (
chargingStation: ChargingStation,
componentName: string,
variableName: string,
defaultSeconds: number
): number {
+ const intervalSeconds = OCPP20ServiceUtils.readVariableAsInteger(
+ chargingStation,
+ componentName,
+ variableName,
+ defaultSeconds
+ )
+ return intervalSeconds > 0
+ ? secondsToMilliseconds(intervalSeconds)
+ : secondsToMilliseconds(defaultSeconds)
+ }
+
+ private static readVariableValue (
+ chargingStation: ChargingStation,
+ componentName: string,
+ variableName: string
+ ): string | undefined {
const variableManager = OCPP20VariableManager.getInstance()
const results = variableManager.getVariables(chargingStation, [
{
},
])
if (results.length > 0 && results[0].attributeValue != null) {
- const intervalSeconds = parseInt(results[0].attributeValue, 10)
- if (!isNaN(intervalSeconds) && intervalSeconds > 0) {
- return secondsToMilliseconds(intervalSeconds)
- }
+ return results[0].attributeValue
}
- return secondsToMilliseconds(defaultSeconds)
+ return undefined
}
private static resolveActiveTransaction (
reservation?: Reservation
status?: ConnectorStatusEnum
transactionBeginMeterValue?: MeterValue
+ transactionDeauthorized?: boolean
+ transactionDeauthorizedEnergyWh?: number
transactionEnergyActiveImportRegisterValue?: number // In Wh
/**
* OCPP 2.0.1 offline-first: Queue of TransactionEvents waiting to be sent
* that occurs after the transaction has been authorized.
*/
transactionIdTokenSent?: boolean
+ transactionMeterValuesSetInterval?: NodeJS.Timeout
/**
* OCPP 2.0.1 E02 compliance: Transaction pending CSMS acknowledgment.
* Blocks duplicate RequestStartTransaction until response handler sets transactionStarted.
transactionPending?: boolean
transactionRemoteStarted?: boolean
transactionSeqNo?: number
- transactionSetInterval?: NodeJS.Timeout
transactionStart?: Date
transactionStarted?: boolean
- transactionTxUpdatedSetInterval?: NodeJS.Timeout
type?: ConnectorEnumType
}
return [...chargingStation.connectors.entries()].map(
([
connectorId,
- {
- transactionEventQueue,
- transactionSetInterval,
- transactionTxUpdatedSetInterval,
- ...connector
- },
+ { transactionEventQueue, transactionMeterValuesSetInterval, ...connector },
]) => ({
connector,
connectorId,
return [...chargingStation.connectors.entries()].map(
([
connectorId,
- {
- transactionEventQueue,
- transactionSetInterval,
- transactionTxUpdatedSetInterval,
- ...connectorStatus
- },
+ { transactionEventQueue, transactionMeterValuesSetInterval, ...connectorStatus },
]) => [connectorId, connectorStatus]
)
}
connectors: [...evseStatus.connectors.entries()].map(
([
connectorId,
- {
- transactionEventQueue,
- transactionSetInterval,
- transactionTxUpdatedSetInterval,
- ...connector
- },
+ { transactionEventQueue, transactionMeterValuesSetInterval, ...connector },
]) => ({
connector,
connectorId,
const connectorsStatus: [number, ConnectorStatus][] = [...evseStatus.connectors.entries()].map(
([
connectorId,
- {
- transactionEventQueue,
- transactionSetInterval,
- transactionTxUpdatedSetInterval,
- ...connector
- },
+ { transactionEventQueue, transactionMeterValuesSetInterval, ...connector },
]) => [connectorId, connector]
)
const { connectors: _, ...evseStatusRest } = evseStatus
// Assert - meter values interval should be created
if (connector1 != null) {
- assert.notStrictEqual(connector1.transactionSetInterval, undefined)
- assert.strictEqual(typeof connector1.transactionSetInterval, 'object')
+ assert.notStrictEqual(connector1.transactionMeterValuesSetInterval, undefined)
+ assert.strictEqual(typeof connector1.transactionMeterValuesSetInterval, 'object')
}
})
})
connector1.transactionId = 100
}
OCPP16ServiceUtils.startPeriodicMeterValues(station, 1, 10000)
- const firstInterval = connector1?.transactionSetInterval
+ const firstInterval = connector1?.transactionMeterValuesSetInterval
// Act
OCPP16ServiceUtils.stopPeriodicMeterValues(station, 1)
OCPP16ServiceUtils.startPeriodicMeterValues(station, 1, 15000)
- const secondInterval = connector1?.transactionSetInterval
+ const secondInterval = connector1?.transactionMeterValuesSetInterval
// Assert - interval should be different
assert.notStrictEqual(secondInterval, undefined)
OCPP16ServiceUtils.stopPeriodicMeterValues(station, 1)
// Assert - interval should be cleared
- assert.strictEqual(connector1?.transactionSetInterval, undefined)
+ assert.strictEqual(connector1?.transactionMeterValuesSetInterval, undefined)
})
})
// Assert - transaction updated interval should be created
if (connector1 != null) {
- assert.notStrictEqual(connector1.transactionTxUpdatedSetInterval, undefined)
- assert.strictEqual(typeof connector1.transactionTxUpdatedSetInterval, 'object')
+ assert.notStrictEqual(connector1.transactionMeterValuesSetInterval, undefined)
+ assert.strictEqual(typeof connector1.transactionMeterValuesSetInterval, 'object')
}
})
})
OCPP20ServiceUtils.stopPeriodicMeterValues(station, 1)
// Assert - interval should be cleared
- assert.strictEqual(connector1?.transactionTxUpdatedSetInterval, undefined)
+ assert.strictEqual(connector1?.transactionMeterValuesSetInterval, undefined)
})
})
})
hasPendingReservation,
hasPendingReservations,
hasReservationExpired,
+ resetConnectorStatus,
validateStationInfo,
} from '../../src/charging-station/Helpers.js'
import {
AvailabilityType,
+ type ChargingProfile,
+ ChargingProfilePurposeType,
type ChargingStationConfiguration,
type ChargingStationInfo,
type ChargingStationTemplate,
type ConnectorStatus,
ConnectorStatusEnum,
+ type MeterValue,
OCPPVersion,
type Reservation,
+ type SampledValueTemplate,
} from '../../src/types/index.js'
import { logger } from '../../src/utils/index.js'
import { standardCleanup } from '../helpers/TestLifecycleHelpers.js'
// Act & Assert
assert.strictEqual(hasPendingReservations(chargingStation), false)
})
+
+ await describe('resetConnectorStatus', async () => {
+ afterEach(() => {
+ standardCleanup()
+ })
+
+ await it('should be a no-op for undefined input', () => {
+ resetConnectorStatus(undefined)
+ })
+
+ await it('should reset all transaction fields', () => {
+ const connectorStatus: ConnectorStatus = {
+ availability: AvailabilityType.Operative,
+ MeterValues: [],
+ transactionBeginMeterValue: { sampledValue: [], timestamp: new Date() } as MeterValue,
+ transactionDeauthorized: true,
+ transactionDeauthorizedEnergyWh: 500,
+ transactionEnergyActiveImportRegisterValue: 1234,
+ transactionEvseSent: true,
+ transactionGroupIdToken: 'group-token',
+ transactionId: 'tx-123',
+ transactionIdTag: 'tag-abc',
+ transactionIdTokenSent: true,
+ transactionPending: true,
+ transactionRemoteStarted: true,
+ transactionSeqNo: 5,
+ transactionStart: new Date(),
+ transactionStarted: true,
+ }
+
+ resetConnectorStatus(connectorStatus)
+
+ assert.strictEqual(connectorStatus.transactionStarted, false)
+ assert.strictEqual(connectorStatus.transactionPending, false)
+ assert.strictEqual(connectorStatus.transactionRemoteStarted, false)
+ assert.strictEqual(connectorStatus.transactionEnergyActiveImportRegisterValue, 0)
+ assert.strictEqual(connectorStatus.transactionId, undefined)
+ assert.strictEqual(connectorStatus.transactionIdTag, undefined)
+ assert.strictEqual(connectorStatus.transactionGroupIdToken, undefined)
+ assert.strictEqual(connectorStatus.transactionStart, undefined)
+ assert.strictEqual(connectorStatus.transactionBeginMeterValue, undefined)
+ assert.strictEqual(connectorStatus.transactionSeqNo, undefined)
+ assert.strictEqual(connectorStatus.transactionEvseSent, undefined)
+ assert.strictEqual(connectorStatus.transactionIdTokenSent, undefined)
+ assert.strictEqual(connectorStatus.transactionDeauthorized, undefined)
+ assert.strictEqual(connectorStatus.transactionDeauthorizedEnergyWh, undefined)
+ assert.strictEqual(connectorStatus.idTagAuthorized, false)
+ assert.strictEqual(connectorStatus.idTagLocalAuthorized, false)
+ assert.strictEqual(connectorStatus.authorizeIdTag, undefined)
+ assert.strictEqual(connectorStatus.localAuthorizeIdTag, undefined)
+ })
+
+ await it('should remove TX_PROFILE charging profiles matching transaction', () => {
+ const txProfile = {
+ chargingProfileId: 1,
+ chargingProfilePurpose: ChargingProfilePurposeType.TX_PROFILE,
+ stackLevel: 0,
+ transactionId: 'tx-123',
+ } as unknown as ChargingProfile
+ const otherProfile = {
+ chargingProfileId: 2,
+ chargingProfilePurpose: ChargingProfilePurposeType.TX_DEFAULT_PROFILE,
+ stackLevel: 0,
+ } as unknown as ChargingProfile
+ const connectorStatus: ConnectorStatus = {
+ availability: AvailabilityType.Operative,
+ chargingProfiles: [txProfile, otherProfile],
+ MeterValues: [],
+ transactionId: 'tx-123',
+ transactionStarted: true,
+ }
+
+ resetConnectorStatus(connectorStatus)
+
+ if (connectorStatus.chargingProfiles == null) {
+ assert.fail('chargingProfiles should not be undefined')
+ }
+ assert.strictEqual(connectorStatus.chargingProfiles.length, 1)
+ assert.strictEqual(
+ connectorStatus.chargingProfiles[0].chargingProfilePurpose,
+ ChargingProfilePurposeType.TX_DEFAULT_PROFILE
+ )
+ })
+
+ await it('should preserve non-transaction fields', () => {
+ const connectorStatus: ConnectorStatus = {
+ availability: AvailabilityType.Operative,
+ MeterValues: [{} as unknown as SampledValueTemplate],
+ status: ConnectorStatusEnum.Available,
+ transactionStarted: true,
+ }
+
+ resetConnectorStatus(connectorStatus)
+
+ assert.strictEqual(connectorStatus.availability, AvailabilityType.Operative)
+ assert.strictEqual(connectorStatus.status, ConnectorStatusEnum.Available)
+ assert.strictEqual(connectorStatus.MeterValues.length, 1)
+ })
+ })
})
// Clear connector transaction state and timers
for (const connectorStatus of station.connectors.values()) {
- if (connectorStatus.transactionSetInterval != null) {
- clearInterval(connectorStatus.transactionSetInterval)
- connectorStatus.transactionSetInterval = undefined
- }
- if (connectorStatus.transactionTxUpdatedSetInterval != null) {
- clearInterval(connectorStatus.transactionTxUpdatedSetInterval)
- connectorStatus.transactionTxUpdatedSetInterval = undefined
+ if (connectorStatus.transactionMeterValuesSetInterval != null) {
+ clearInterval(connectorStatus.transactionMeterValuesSetInterval)
+ connectorStatus.transactionMeterValuesSetInterval = undefined
}
}
// Clear EVSE connector transaction state and timers
for (const evseStatus of station.evses.values()) {
for (const connectorStatus of evseStatus.connectors.values()) {
- if (connectorStatus.transactionSetInterval != null) {
- clearInterval(connectorStatus.transactionSetInterval)
- connectorStatus.transactionSetInterval = undefined
- }
- if (connectorStatus.transactionTxUpdatedSetInterval != null) {
- clearInterval(connectorStatus.transactionTxUpdatedSetInterval)
- connectorStatus.transactionTxUpdatedSetInterval = undefined
+ if (connectorStatus.transactionMeterValuesSetInterval != null) {
+ clearInterval(connectorStatus.transactionMeterValuesSetInterval)
+ connectorStatus.transactionMeterValuesSetInterval = undefined
}
}
}
status.transactionEnergyActiveImportRegisterValue = 0
// Clear transaction interval
- if (status.transactionSetInterval != null) {
- clearInterval(status.transactionSetInterval)
- status.transactionSetInterval = undefined
+ if (status.transactionMeterValuesSetInterval != null) {
+ clearInterval(status.transactionMeterValuesSetInterval)
+ status.transactionMeterValuesSetInterval = undefined
}
}
// Clean up any running timers
for (let connectorId = 1; connectorId <= 3; connectorId++) {
const connector = mockStation.getConnectorStatus(connectorId)
- if (connector?.transactionTxUpdatedSetInterval != null) {
- clearInterval(connector.transactionTxUpdatedSetInterval)
- connector.transactionTxUpdatedSetInterval = undefined
+ if (connector?.transactionMeterValuesSetInterval != null) {
+ clearInterval(connector.transactionMeterValuesSetInterval)
+ connector.transactionMeterValuesSetInterval = undefined
}
}
standardCleanup()
await startPeriodicMeterValues(ocpp16Station, 1, 60000)
const connector = ocpp16Station.getConnectorStatus(1)
- assert.strictEqual(connector?.transactionTxUpdatedSetInterval, undefined)
+ assert.strictEqual(connector?.transactionMeterValuesSetInterval, undefined)
})
})
// Zero interval should not start timer
// This is verified by the implementation logging debug message
- assert.strictEqual(connector.transactionTxUpdatedSetInterval, undefined)
+ assert.strictEqual(connector.transactionMeterValuesSetInterval, undefined)
})
await it('should not start timer when interval is negative', () => {
assert(connector != null)
// Negative interval should not start timer
- assert.strictEqual(connector.transactionTxUpdatedSetInterval, undefined)
+ assert.strictEqual(connector.transactionMeterValuesSetInterval, undefined)
})
await it('should handle non-existent connector gracefully', () => {
connectorStatus.transactionStarted = true
connectorStatus.transactionId = transactionId
connectorStatus.transactionEnergyActiveImportRegisterValue = 100
+ connectorStatus.transactionDeauthorized = true
+ connectorStatus.transactionDeauthorizedEnergyWh = 50
}
// Act
if (postStatus != null) {
assert.strictEqual(postStatus.transactionStarted, false)
assert.strictEqual(postStatus.transactionId, undefined)
+ assert.strictEqual(postStatus.transactionDeauthorized, undefined)
+ assert.strictEqual(postStatus.transactionDeauthorizedEnergyWh, undefined)
}
})
)
})
+ await it('should not terminate when StopTxOnInvalidId is false', async () => {
+ // Arrange
+ const connectorId = 1
+ const transactionId = generateUUID()
+ const connectorStatus = mockTracking.station.getConnectorStatus(connectorId)
+ assert.notStrictEqual(connectorStatus, undefined)
+ if (connectorStatus != null) {
+ connectorStatus.transactionStarted = true
+ connectorStatus.transactionId = transactionId
+ connectorStatus.transactionEnergyActiveImportRegisterValue = 0
+ }
+ OCPP20VariableManager.getInstance().setVariables(mockTracking.station, [
+ {
+ attributeType: AttributeEnumType.Actual,
+ attributeValue: 'false',
+ component: { name: OCPP20ComponentName.TxCtrlr },
+ variable: { name: OCPP20RequiredVariableName.StopTxOnInvalidId },
+ },
+ ])
+
+ // Act
+ await OCPP20ServiceUtils.requestDeauthorizeTransaction(mockTracking.station, connectorId, 1)
+
+ // Assert — only Updated(Deauthorized), no Ended
+ const txEvents = mockTracking.sentRequests.filter(
+ r => r.command === (OCPP20RequestCommand.TRANSACTION_EVENT as string)
+ )
+ assert.strictEqual(txEvents.length, 1)
+ assert.strictEqual(txEvents[0].payload.eventType, OCPP20TransactionEventEnumType.Updated)
+ assert.strictEqual(
+ txEvents[0].payload.triggerReason,
+ OCPP20TriggerReasonEnumType.Deauthorized
+ )
+
+ // Transaction should still be active
+ const postStatus = mockTracking.station.getConnectorStatus(connectorId)
+ if (postStatus != null) {
+ assert.strictEqual(postStatus.transactionStarted, true)
+ assert.strictEqual(postStatus.transactionId, transactionId)
+ }
+
+ OCPP20VariableManager.getInstance().resetRuntimeOverrides()
+ })
+
+ await it('should track deauth state for deferred termination via periodic meter values', () => {
+ const connectorId = 1
+ const transactionId = generateUUID()
+ const connectorStatus = mockTracking.station.getConnectorStatus(connectorId)
+ if (connectorStatus == null) {
+ assert.fail('connectorStatus should not be undefined')
+ }
+ connectorStatus.transactionStarted = true
+ connectorStatus.transactionId = transactionId
+ connectorStatus.transactionEnergyActiveImportRegisterValue = 500
+ connectorStatus.transactionDeauthorized = true
+ connectorStatus.transactionDeauthorizedEnergyWh = 500
+
+ assert.strictEqual(connectorStatus.transactionDeauthorized, true)
+ assert.strictEqual(connectorStatus.transactionDeauthorizedEnergyWh, 500)
+ assert.strictEqual(connectorStatus.transactionStarted, true)
+ })
+
await it('should propagate error and skip cleanup if Updated event fails', async () => {
const connectorId = 1
const transactionId = generateUUID()
connector.idTagLocalAuthorized = false
// Clear any transaction interval
- if (connector.transactionSetInterval != null) {
- clearInterval(connector.transactionSetInterval)
- connector.transactionSetInterval = undefined
+ if (connector.transactionMeterValuesSetInterval != null) {
+ clearInterval(connector.transactionMeterValuesSetInterval)
+ connector.transactionMeterValuesSetInterval = undefined
}
}
bootStatus: 'Available',
MeterValues: [],
transactionEventQueue: [],
- transactionSetInterval: interval1 as unknown as NodeJS.Timeout,
- transactionTxUpdatedSetInterval: interval2 as unknown as NodeJS.Timeout,
+ transactionMeterValuesSetInterval: interval1 as unknown as NodeJS.Timeout,
} as unknown as ConnectorStatus)
const station = createMockStationForConfigUtils({ connectors })
assert.strictEqual(result.length, 2)
for (const [, connector] of result) {
- assert.ok(!('transactionSetInterval' in connector))
+ assert.ok(!('transactionMeterValuesSetInterval' in connector))
assert.ok(!('transactionEventQueue' in connector))
- assert.ok(!('transactionTxUpdatedSetInterval' in connector))
}
assert.strictEqual(result[0][0], 0)
assert.strictEqual(result[1][0], 1)
MeterValues: [],
transactionEventQueue: undefined,
transactionId: 42,
- transactionSetInterval: undefined,
+ transactionMeterValuesSetInterval: undefined,
transactionStarted: true,
- transactionTxUpdatedSetInterval: undefined,
} as unknown as ConnectorStatus)
const station = createMockStationForConfigUtils({ connectors })
availability: AvailabilityType.Operative,
MeterValues: [],
transactionEventQueue: [],
- transactionSetInterval: undefined,
- transactionTxUpdatedSetInterval: undefined,
+ transactionMeterValuesSetInterval: undefined,
} as unknown as ConnectorStatus)
const evses = new Map<number, EvseStatus>()
availability: AvailabilityType.Operative,
MeterValues: [],
transactionEventQueue: [],
- transactionSetInterval: undefined,
- transactionTxUpdatedSetInterval: undefined,
+ transactionMeterValuesSetInterval: undefined,
} as unknown as ConnectorStatus)
const evses = new Map<number, EvseStatus>()
+ evses.set(0, {
+ availability: AvailabilityType.Operative,
+ connectors: new Map<number, ConnectorStatus>(),
+ })
evses.set(1, {
availability: AvailabilityType.Operative,
connectors: evseConnectors,
const station = createMockStationForConfigUtils({ evses })
const result = buildEvsesStatus(station)
- const evse1 = result[0][1]
+ const evse1 = result.find(([id]) => id === 1)?.[1]
+ assert.ok(evse1 != null)
const connectorsStatus = evse1.connectorsStatus as [number, ConnectorStatus][]
assert.strictEqual(connectorsStatus.length, 1)
assert.strictEqual(connectorsStatus[0][0], 1)
const connector = connectorsStatus[0][1]
- assert.ok(!('transactionSetInterval' in connector))
+ assert.ok(!('transactionMeterValuesSetInterval' in connector))
assert.ok(!('transactionEventQueue' in connector))
- assert.ok(!('transactionTxUpdatedSetInterval' in connector))
})
await it('should preserve connector IDs across serialization', () => {
availability: AvailabilityType.Operative,
MeterValues: [],
transactionEventQueue: [],
- transactionSetInterval: undefined,
- transactionTxUpdatedSetInterval: undefined,
+ transactionMeterValuesSetInterval: undefined,
} as unknown as ConnectorStatus)
const station = createMockStationForConfigUtils({ connectors })
assert.strictEqual(result[0].connectorId, 0)
assert.strictEqual(result[1].connectorId, 1)
assert.strictEqual(result[1].connector.availability, AvailabilityType.Operative)
- assert.ok(!('transactionSetInterval' in result[1].connector))
+ assert.ok(!('transactionMeterValuesSetInterval' in result[1].connector))
assert.ok(!('transactionEventQueue' in result[1].connector))
- assert.ok(!('transactionTxUpdatedSetInterval' in result[1].connector))
})
await it('should handle empty connectors map', () => {
availability: AvailabilityType.Operative,
MeterValues: [],
transactionEventQueue: [],
- transactionSetInterval: undefined,
- transactionTxUpdatedSetInterval: undefined,
+ transactionMeterValuesSetInterval: undefined,
} as unknown as ConnectorStatus)
const evses = new Map<number, EvseStatus>()
assert.strictEqual(result[1].evseId, 1)
assert.strictEqual(result[1].connectors.length, 1)
assert.strictEqual(result[1].connectors[0].connectorId, 1)
- assert.ok(!('transactionSetInterval' in result[1].connectors[0].connector))
+ assert.ok(!('transactionMeterValuesSetInterval' in result[1].connectors[0].connector))
assert.ok(!('transactionEventQueue' in result[1].connectors[0].connector))
})