(v, reason) => ({
attributeStatus: GetVariableStatusEnumType.Rejected,
attributeStatusInfo: {
- additionalInfo: reason.info,
-
+ additionalInfo: reason.additionalInfo,
reasonCode: reason.reasonCode,
},
attributeType: v.attributeType,
logger
)
if (preEnforcement.rejected) {
- getVariablesResponse.getVariableResult =
- preEnforcement.results as typeof getVariablesResponse.getVariableResult
+ getVariablesResponse.getVariableResult = preEnforcement.results
return getVariablesResponse
}
(v, reason) => ({
attributeStatus: GetVariableStatusEnumType.Rejected,
attributeStatusInfo: {
- additionalInfo: reason.info,
-
- reasonCode: ReasonCodeEnumType[reason.reasonCode as keyof typeof ReasonCodeEnumType],
+ additionalInfo: reason.additionalInfo,
+ reasonCode: reason.reasonCode,
},
attributeType: v.attributeType,
component: v.component,
variable: v.variable,
}),
logger
- ) as typeof getVariablesResponse.getVariableResult
+ )
logger.debug(
`${chargingStation.logPrefix()} ${moduleName}.handleRequestGetVariables: Processed ${commandPayload.getVariableData.length.toString()} variable requests, returning ${results.length.toString()} results`
(v, reason) => ({
attributeStatus: SetVariableStatusEnumType.Rejected,
attributeStatusInfo: {
- additionalInfo: reason.info,
-
+ additionalInfo: reason.additionalInfo,
reasonCode: reason.reasonCode,
},
attributeType: v.attributeType ?? AttributeEnumType.Actual,
logger
)
if (preEnforcement.rejected) {
- setVariablesResponse.setVariableResult =
- preEnforcement.results as typeof setVariablesResponse.setVariableResult
+ setVariablesResponse.setVariableResult = preEnforcement.results
return setVariablesResponse
}
(v, reason) => ({
attributeStatus: SetVariableStatusEnumType.Rejected,
attributeStatusInfo: {
- additionalInfo: reason.info,
-
- reasonCode: ReasonCodeEnumType[reason.reasonCode as keyof typeof ReasonCodeEnumType],
+ additionalInfo: reason.additionalInfo,
+ reasonCode: reason.reasonCode,
},
attributeType: v.attributeType ?? AttributeEnumType.Actual,
component: v.component,
variable: v.variable,
}),
logger
- ) as typeof setVariablesResponse.setVariableResult
+ )
logger.debug(
`${chargingStation.logPrefix()} ${moduleName}.handleRequestSetVariables: Processed ${commandPayload.setVariableData.length.toString()} variable requests, returning ${results.length.toString()} results`
const moduleName = 'OCPP20ServiceUtils'
+export interface RejectionReason {
+ additionalInfo: string
+ reasonCode: ReasonCodeEnumType
+}
+
export class OCPP20ServiceUtils extends OCPPServiceUtils {
private static readonly incomingRequestSchemaNames: readonly [
OCPP20IncomingRequestCommand,
])
public static enforceMessageLimits<
- T extends { attributeType?: unknown; component: unknown; variable: unknown }
+ T extends { attributeType?: unknown; component: unknown; variable: unknown },
+ R
>(
chargingStation: { logPrefix: () => string },
moduleName: string,
data: T[],
itemsLimit: number,
bytesLimit: number,
- buildRejected: (item: T, reason: { info: string; reasonCode: ReasonCodeEnumType }) => unknown,
+ buildRejected: (item: T, reason: RejectionReason) => R,
logger: { debug: (...args: unknown[]) => void }
- ): { rejected: boolean; results: unknown[] } {
+ ): { rejected: boolean; results: R[] } {
if (itemsLimit > 0 && data.length > itemsLimit) {
const results = data.map(d =>
buildRejected(d, {
- info: `ItemsPerMessage limit ${itemsLimit.toString()} exceeded (${data.length.toString()} requested)`,
+ additionalInfo: `ItemsPerMessage limit ${itemsLimit.toString()} exceeded (${data.length.toString()} requested)`,
reasonCode: ReasonCodeEnumType.TooManyElements,
})
)
if (estimatedSize > bytesLimit) {
const results = data.map(d =>
buildRejected(d, {
- info: `BytesPerMessage limit ${bytesLimit.toString()} exceeded (estimated ${estimatedSize.toString()} bytes)`,
+ additionalInfo: `BytesPerMessage limit ${bytesLimit.toString()} exceeded (estimated ${estimatedSize.toString()} bytes)`,
reasonCode: ReasonCodeEnumType.TooLargeElement,
})
)
}
public static enforcePostCalculationBytesLimit<
- T extends { attributeType?: unknown; component: unknown; variable: unknown }
+ T extends { attributeType?: unknown; component: unknown; variable: unknown },
+ R
>(
chargingStation: { logPrefix: () => string },
moduleName: string,
context: string,
originalData: T[],
- currentResults: unknown[],
+ currentResults: R[],
bytesLimit: number,
- buildRejected: (item: T, reason: { info: string; reasonCode: ReasonCodeEnumType }) => unknown,
+ buildRejected: (item: T, reason: RejectionReason) => R,
logger: { debug: (...args: unknown[]) => void }
- ): unknown[] {
+ ): R[] {
if (bytesLimit > 0) {
try {
const actualSize = Buffer.byteLength(JSON.stringify(currentResults), 'utf8')
if (actualSize > bytesLimit) {
const results = originalData.map(d =>
buildRejected(d, {
- info: `BytesPerMessage limit ${bytesLimit.toString()} exceeded (actual ${actualSize.toString()} bytes)`,
+ additionalInfo: `BytesPerMessage limit ${bytesLimit.toString()} exceeded (actual ${actualSize.toString()} bytes)`,
reasonCode: ReasonCodeEnumType.TooLargeElement,
})
)
import assert from 'node:assert/strict'
import { afterEach, describe, it } from 'node:test'
-import { OCPP20ServiceUtils } from '../../../../src/charging-station/ocpp/2.0/OCPP20ServiceUtils.js'
+import {
+ OCPP20ServiceUtils,
+ type RejectionReason,
+} from '../../../../src/charging-station/ocpp/2.0/OCPP20ServiceUtils.js'
import { ReasonCodeEnumType } from '../../../../src/types/index.js'
import { standardCleanup } from '../../../helpers/TestLifecycleHelpers.js'
}
interface RejectedResult {
- info: string
+ additionalInfo: string
original: TestItem
reasonCode: ReasonCodeEnumType
}
/** @returns A builder function that creates rejected result objects */
function makeRejectedBuilder () {
- return (
- item: TestItem,
- reason: { info: string; reasonCode: ReasonCodeEnumType }
- ): RejectedResult => ({
- info: reason.info,
+ return (item: TestItem, reason: RejectionReason): RejectedResult => ({
+ additionalInfo: reason.additionalInfo,
original: item,
reasonCode: reason.reasonCode,
})
assert.strictEqual(result.rejected, true)
assert.strictEqual(result.results.length, 3)
- for (const r of result.results as RejectedResult[]) {
+ for (const r of result.results) {
assert.strictEqual(r.reasonCode, ReasonCodeEnumType.TooManyElements)
- assert.ok(r.info.includes('ItemsPerMessage limit 2'))
+ assert.ok(r.additionalInfo.includes('ItemsPerMessage limit 2'))
}
})
assert.strictEqual(result.rejected, true)
assert.strictEqual(result.results.length, 2)
- for (const r of result.results as RejectedResult[]) {
+ for (const r of result.results) {
assert.strictEqual(r.reasonCode, ReasonCodeEnumType.TooManyElements)
}
})
assert.strictEqual(result.rejected, true)
assert.strictEqual(result.results.length, 1)
- const r = (result.results as RejectedResult[])[0]
+ const r = result.results[0]
assert.strictEqual(r.reasonCode, ReasonCodeEnumType.TooLargeElement)
- assert.ok(r.info.includes('BytesPerMessage limit 1'))
+ assert.ok(r.additionalInfo.includes('BytesPerMessage limit 1'))
})
await it('should reject all items with TooLargeElement for multiple items over bytes limit', () => {
assert.strictEqual(result.rejected, true)
assert.strictEqual(result.results.length, 2)
- for (const r of result.results as RejectedResult[]) {
+ for (const r of result.results) {
assert.strictEqual(r.reasonCode, ReasonCodeEnumType.TooLargeElement)
}
})
)
assert.strictEqual(result.rejected, true)
- for (const r of result.results as RejectedResult[]) {
+ for (const r of result.results) {
assert.strictEqual(r.reasonCode, ReasonCodeEnumType.TooManyElements)
}
})
const station = makeMockStation()
const logger = makeMockLogger()
const item = makeItem('WebSocketPingInterval', 'xyz')
- const capturedReasons: { info: string; reasonCode: ReasonCodeEnumType }[] = []
+ const capturedReasons: RejectionReason[] = []
OCPP20ServiceUtils.enforceMessageLimits(
station,
assert.strictEqual(capturedReasons.length, 1)
assert.strictEqual(capturedReasons[0].reasonCode, ReasonCodeEnumType.TooLargeElement)
- assert.strictEqual(typeof capturedReasons[0].info, 'string')
- assert.ok(capturedReasons[0].info.length > 0)
+ assert.strictEqual(typeof capturedReasons[0].additionalInfo, 'string')
+ assert.ok(capturedReasons[0].additionalInfo.length > 0)
})
})
})