]> Piment Noir Git Repositories - e-mobility-charging-stations-simulator.git/commitdiff
fix(ocpp2.0): add proper response handlers for certificate commands + handler coverag... main
authorJérôme Benoit <jerome.benoit@sap.com>
Fri, 20 Mar 2026 20:39:36 +0000 (21:39 +0100)
committerJérôme Benoit <jerome.benoit@sap.com>
Fri, 20 Mar 2026 20:39:36 +0000 (21:39 +0100)
Replace emptyResponseHandler with proper logging handlers for
Get15118EVCertificate, GetCertificateStatus, and SignCertificate
responses. Add handler registration coverage tests for both OCPP 1.6
and 2.0: every RequestCommand must have a response handler, every
IncomingRequestCommand must have an incoming request handler.

src/charging-station/ocpp/2.0/OCPP20ResponseService.ts
tests/charging-station/ocpp/1.6/OCPP16SchemaValidation.test.ts
tests/charging-station/ocpp/2.0/OCPP20SchemaValidation.test.ts

index c88823e3c724e7f793b2b715a6be953f708bb890..75a737ad9f44a7bcc99147eb1dcdc26a0367681d 100644 (file)
@@ -6,8 +6,11 @@ import {
   ConnectorStatusEnum,
   type JsonType,
   OCPP20AuthorizationStatusEnumType,
+  type OCPP20AuthorizeResponse,
   type OCPP20BootNotificationResponse,
   type OCPP20FirmwareStatusNotificationResponse,
+  type OCPP20Get15118EVCertificateResponse,
+  type OCPP20GetCertificateStatusResponse,
   type OCPP20HeartbeatResponse,
   type OCPP20IncomingRequestCommand,
   type OCPP20LogStatusNotificationResponse,
@@ -17,6 +20,7 @@ import {
   OCPP20OptionalVariableName,
   OCPP20RequestCommand,
   type OCPP20SecurityEventNotificationResponse,
+  type OCPP20SignCertificateResponse,
   type OCPP20StatusNotificationResponse,
   OCPP20TransactionEventEnumType,
   type OCPP20TransactionEventRequest,
@@ -93,6 +97,7 @@ export class OCPP20ResponseService extends OCPPResponseService {
   public constructor () {
     super(OCPPVersion.VERSION_201)
     this.responseHandlers = new Map<RequestCommand, ResponseHandler>([
+      [OCPP20RequestCommand.AUTHORIZE, this.handleResponseAuthorize.bind(this) as ResponseHandler],
       [
         OCPP20RequestCommand.BOOT_NOTIFICATION,
         this.handleResponseBootNotification.bind(this) as ResponseHandler,
@@ -101,6 +106,14 @@ export class OCPP20ResponseService extends OCPPResponseService {
         OCPP20RequestCommand.FIRMWARE_STATUS_NOTIFICATION,
         this.handleResponseFirmwareStatusNotification.bind(this) as ResponseHandler,
       ],
+      [
+        OCPP20RequestCommand.GET_15118_EV_CERTIFICATE,
+        this.handleResponseGet15118EVCertificate.bind(this) as ResponseHandler,
+      ],
+      [
+        OCPP20RequestCommand.GET_CERTIFICATE_STATUS,
+        this.handleResponseGetCertificateStatus.bind(this) as ResponseHandler,
+      ],
       [OCPP20RequestCommand.HEARTBEAT, this.handleResponseHeartbeat.bind(this) as ResponseHandler],
       [
         OCPP20RequestCommand.LOG_STATUS_NOTIFICATION,
@@ -122,6 +135,10 @@ export class OCPP20ResponseService extends OCPPResponseService {
         OCPP20RequestCommand.SECURITY_EVENT_NOTIFICATION,
         this.handleResponseSecurityEventNotification.bind(this) as ResponseHandler,
       ],
+      [
+        OCPP20RequestCommand.SIGN_CERTIFICATE,
+        this.handleResponseSignCertificate.bind(this) as ResponseHandler,
+      ],
       [
         OCPP20RequestCommand.STATUS_NOTIFICATION,
         this.handleResponseStatusNotification.bind(this) as ResponseHandler,
@@ -154,6 +171,15 @@ export class OCPP20ResponseService extends OCPPResponseService {
     )
   }
 
+  private handleResponseAuthorize (
+    chargingStation: ChargingStation,
+    payload: OCPP20AuthorizeResponse
+  ): void {
+    logger.debug(
+      `${chargingStation.logPrefix()} ${moduleName}.handleResponseAuthorize: Authorize response received, status: ${payload.idTokenInfo.status}`
+    )
+  }
+
   private handleResponseBootNotification (
     chargingStation: ChargingStation,
     payload: OCPP20BootNotificationResponse
@@ -213,6 +239,24 @@ export class OCPP20ResponseService extends OCPPResponseService {
     )
   }
 
+  private handleResponseGet15118EVCertificate (
+    chargingStation: ChargingStation,
+    payload: OCPP20Get15118EVCertificateResponse
+  ): void {
+    logger.debug(
+      `${chargingStation.logPrefix()} ${moduleName}.handleResponseGet15118EVCertificate: Get15118EVCertificate response received, status: ${payload.status}`
+    )
+  }
+
+  private handleResponseGetCertificateStatus (
+    chargingStation: ChargingStation,
+    payload: OCPP20GetCertificateStatusResponse
+  ): void {
+    logger.debug(
+      `${chargingStation.logPrefix()} ${moduleName}.handleResponseGetCertificateStatus: GetCertificateStatus response received, status: ${payload.status}`
+    )
+  }
+
   private handleResponseHeartbeat (
     chargingStation: ChargingStation,
     payload: OCPP20HeartbeatResponse
@@ -267,6 +311,15 @@ export class OCPP20ResponseService extends OCPPResponseService {
     )
   }
 
+  private handleResponseSignCertificate (
+    chargingStation: ChargingStation,
+    payload: OCPP20SignCertificateResponse
+  ): void {
+    logger.debug(
+      `${chargingStation.logPrefix()} ${moduleName}.handleResponseSignCertificate: SignCertificate response received, status: ${payload.status}`
+    )
+  }
+
   private handleResponseStatusNotification (
     chargingStation: ChargingStation,
     payload: OCPP20StatusNotificationResponse
index 93aa3af785ba024d554050ee2076744d54a75b4a..1bbd1f749615dba07c582643f0b90195217f8bb5 100644 (file)
@@ -14,6 +14,8 @@ import { join } from 'node:path'
 import { afterEach, describe, it } from 'node:test'
 import { fileURLToPath } from 'node:url'
 
+import { OCPP16IncomingRequestService } from '../../../../src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.js'
+import { OCPP16ResponseService } from '../../../../src/charging-station/ocpp/1.6/OCPP16ResponseService.js'
 import { OCPP16ServiceUtils } from '../../../../src/charging-station/ocpp/1.6/OCPP16ServiceUtils.js'
 import { OCPP16IncomingRequestCommand, OCPP16RequestCommand } from '../../../../src/types/index.js'
 import { standardCleanup } from '../../../helpers/TestLifecycleHelpers.js'
@@ -324,5 +326,26 @@ await describe('OCPP16SchemaValidation', async () => {
         )
       }
     })
+
+    await it('should register a response handler for every OCPP16RequestCommand', () => {
+      const responseService = new OCPP16ResponseService()
+      const handlers = (responseService as unknown as { responseHandlers: Map<string, unknown> })
+        .responseHandlers
+      const registered = new Set(handlers.keys())
+      for (const command of Object.values(OCPP16RequestCommand)) {
+        assert.ok(registered.has(command), `missing response handler for: ${command}`)
+      }
+    })
+
+    await it('should register an incoming request handler for every OCPP16IncomingRequestCommand', () => {
+      const incomingService = new OCPP16IncomingRequestService()
+      const handlers = (
+        incomingService as unknown as { incomingRequestHandlers: Map<string, unknown> }
+      ).incomingRequestHandlers
+      const registered = new Set(handlers.keys())
+      for (const command of Object.values(OCPP16IncomingRequestCommand)) {
+        assert.ok(registered.has(command), `missing incoming request handler for: ${command}`)
+      }
+    })
   })
 })
index 59fa9adcd2c23b0a62bcccce7423b46d9cc3e42e..f0ca0785723ed32ebd748b33889638d9d1dfbb92 100644 (file)
@@ -17,6 +17,8 @@ import { join } from 'node:path'
 import { afterEach, describe, it } from 'node:test'
 import { fileURLToPath } from 'node:url'
 
+import { OCPP20IncomingRequestService } from '../../../../src/charging-station/ocpp/2.0/OCPP20IncomingRequestService.js'
+import { OCPP20ResponseService } from '../../../../src/charging-station/ocpp/2.0/OCPP20ResponseService.js'
 import { OCPP20ServiceUtils } from '../../../../src/charging-station/ocpp/2.0/OCPP20ServiceUtils.js'
 import { OCPP20IncomingRequestCommand, OCPP20RequestCommand } from '../../../../src/types/index.js'
 import { standardCleanup } from '../../../helpers/TestLifecycleHelpers.js'
@@ -254,5 +256,26 @@ await describe('OCPP 2.0 schema validation — negative tests', async () => {
         )
       }
     })
+
+    await it('should register a response handler for every OCPP20RequestCommand', () => {
+      const responseService = new OCPP20ResponseService()
+      const handlers = (responseService as unknown as { responseHandlers: Map<string, unknown> })
+        .responseHandlers
+      const registered = new Set(handlers.keys())
+      for (const command of Object.values(OCPP20RequestCommand)) {
+        assert.ok(registered.has(command), `missing response handler for: ${command}`)
+      }
+    })
+
+    await it('should register an incoming request handler for every OCPP20IncomingRequestCommand', () => {
+      const incomingService = new OCPP20IncomingRequestService()
+      const handlers = (
+        incomingService as unknown as { incomingRequestHandlers: Map<string, unknown> }
+      ).incomingRequestHandlers
+      const registered = new Set(handlers.keys())
+      for (const command of Object.values(OCPP20IncomingRequestCommand)) {
+        assert.ok(registered.has(command), `missing incoming request handler for: ${command}`)
+      }
+    })
   })
 })