UI Services: add status notification command
authorJérôme Benoit <jerome.benoit@sap.com>
Sun, 4 Sep 2022 22:44:53 +0000 (00:44 +0200)
committerJérôme Benoit <jerome.benoit@sap.com>
Sun, 4 Sep 2022 22:44:53 +0000 (00:44 +0200)
Signed-off-by: Jérôme Benoit <jerome.benoit@sap.com>
README.md
src/charging-station/ChargingStationWorkerBroadcastChannel.ts
src/charging-station/ui-server/ui-services/UIService001.ts
src/types/UIProtocol.ts
src/types/WorkerBroadcastChannel.ts
src/types/ocpp/1.6/Requests.ts

index d80538029b6f6b891bf643c13bab95e32c89b9a9..f03560dfea96b41ba8c00dcae6ade599d7c2c937 100644 (file)
--- a/README.md
+++ b/README.md
@@ -459,7 +459,8 @@ Set the Websocket header _Sec-Websocket-Protocol_ to `ui0.0.1`.
   `PDU`: {  
   `status`: 'success' | 'failure',  
   `hashIdsSucceeded`: charging station unique identifier strings array,  
-  `hashIdsFailed`: charging station unique identifier strings array (optional)  
+  `hashIdsFailed`: charging station unique identifier strings array (optional),  
+  `responsesFailed`: failed responses payload array (optional)  
   }
 
 ###### Stop Transaction
@@ -570,6 +571,23 @@ Set the Websocket header _Sec-Websocket-Protocol_ to `ui0.0.1`.
   `hashIdsFailed`: charging station unique identifier strings array (optional)  
   }
 
+###### Stop Automatic Transaction Generator
+
+- Request:  
+  `ProcedureName`: 'StatusNotification'  
+  `PDU`: {  
+  `hashIds`: charging station unique identifier strings array (optional, default: all charging stations),  
+  `connectorId`: connector id integer  
+  }
+
+- Response:  
+  `PDU`: {  
+  `status`: 'success' | 'failure',  
+  `hashIdsSucceeded`: charging station unique identifier strings array,  
+  `hashIdsFailed`: charging station unique identifier strings array (optional)  
+  `responsesFailed`: failed responses payload array (optional)  
+  }
+
 ## Support, Feedback, Contributing
 
 This project is open to feature requests/suggestions, bug reports etc. via [GitHub issues](https://github.com/SAP/e-mobility-charging-stations-simulator/issues). Contribution and feedback are encouraged and always welcome. For more information about how to contribute, the project structure, as well as additional contribution information, see our [Contribution Guidelines](CONTRIBUTING.md).
index a31d9779dff7b841bba18c31816ccb1c87c14929..ebc100990c943fae4abeb804760292258b8ee409 100644 (file)
@@ -1,5 +1,7 @@
 import BaseError from '../exception/BaseError';
-import { RequestCommand } from '../types/ocpp/Requests';
+import type OCPPError from '../exception/OCPPError';
+import { RequestCommand, type StatusNotificationRequest } from '../types/ocpp/Requests';
+import type { StatusNotificationResponse } from '../types/ocpp/Responses';
 import {
   AuthorizationStatus,
   StartTransactionRequest,
@@ -16,12 +18,16 @@ import {
 } from '../types/WorkerBroadcastChannel';
 import { ResponseStatus } from '../ui/web/src/types/UIProtocol';
 import logger from '../utils/Logger';
+import Utils from '../utils/Utils';
 import type ChargingStation from './ChargingStation';
 import WorkerBroadcastChannel from './WorkerBroadcastChannel';
 
 const moduleName = 'ChargingStationWorkerBroadcastChannel';
 
-type CommandResponse = StartTransactionResponse | StopTransactionResponse;
+type CommandResponse =
+  | StartTransactionResponse
+  | StopTransactionResponse
+  | StatusNotificationResponse;
 
 export default class ChargingStationWorkerBroadcastChannel extends WorkerBroadcastChannel {
   private readonly chargingStation: ChargingStation;
@@ -88,6 +94,7 @@ export default class ChargingStationWorkerBroadcastChannel extends WorkerBroadca
         commandResponse,
         errorMessage: (error as Error).message,
         errorStack: (error as Error).stack,
+        errorDetails: (error as OCPPError).details,
       };
     }
     this.sendResponse([uuid, responsePayload]);
@@ -144,6 +151,21 @@ export default class ChargingStationWorkerBroadcastChannel extends WorkerBroadca
       case BroadcastChannelProcedureName.STOP_AUTOMATIC_TRANSACTION_GENERATOR:
         this.chargingStation.stopAutomaticTransactionGenerator(requestPayload.connectorIds);
         break;
+      case BroadcastChannelProcedureName.STATUS_NOTIFICATION:
+        return this.chargingStation.ocppRequestService.requestHandler<
+          StatusNotificationRequest,
+          StatusNotificationResponse
+        >(this.chargingStation, RequestCommand.STATUS_NOTIFICATION, {
+          connectorId: requestPayload.connectorId,
+          errorCode: requestPayload.errorCode,
+          status: requestPayload.status,
+          ...(requestPayload.info && { info: requestPayload.info }),
+          ...(requestPayload.timestamp && { timestamp: requestPayload.timestamp }),
+          ...(requestPayload.vendorId && { vendorId: requestPayload.vendorId }),
+          ...(requestPayload.vendorErrorCode && {
+            vendorErrorCode: requestPayload.vendorErrorCode,
+          }),
+        });
       default:
         // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
         throw new BaseError(`Unknown worker broadcast channel command: ${command}`);
@@ -151,7 +173,10 @@ export default class ChargingStationWorkerBroadcastChannel extends WorkerBroadca
   }
 
   private commandResponseToResponseStatus(commandResponse: CommandResponse): ResponseStatus {
-    if (commandResponse?.idTagInfo?.status === AuthorizationStatus.ACCEPTED) {
+    if (
+      Utils.isEmptyObject(commandResponse) ||
+      commandResponse?.idTagInfo?.status === AuthorizationStatus.ACCEPTED
+    ) {
       return ResponseStatus.SUCCESS;
     }
     return ResponseStatus.FAILURE;
index 4740b7d738e2c99829232ba86dcfe9326648c571..74403ceaaed5cbbbca6b99bc4b740f1da13519b6 100644 (file)
@@ -43,6 +43,10 @@ export default class UIService001 extends AbstractUIService {
       ProcedureName.STOP_AUTOMATIC_TRANSACTION_GENERATOR,
       this.handleStopAutomaticTransactionGenerator.bind(this) as ProtocolRequestHandler
     );
+    this.requestHandlers.set(
+      ProcedureName.STATUS_NOTIFICATION,
+      this.handleStatusNotification.bind(this) as ProtocolRequestHandler
+    );
   }
 
   private handleStartChargingStation(uuid: string, payload: RequestPayload): void {
@@ -96,4 +100,12 @@ export default class UIService001 extends AbstractUIService {
       payload
     );
   }
+
+  private handleStatusNotification(uuid: string, payload: RequestPayload): void {
+    this.sendBroadcastChannelRequest(
+      uuid,
+      BroadcastChannelProcedureName.STATUS_NOTIFICATION,
+      payload
+    );
+  }
 }
index 0e4fb77a2c9658a904c357b7cf65cb65fa3e724e..d995e096676fd7d40a3944defb8cab8d9f91fb2d 100644 (file)
@@ -38,6 +38,7 @@ export enum ProcedureName {
   STOP_TRANSACTION = 'stopTransaction',
   START_AUTOMATIC_TRANSACTION_GENERATOR = 'startAutomaticTransactionGenerator',
   STOP_AUTOMATIC_TRANSACTION_GENERATOR = 'stopAutomaticTransactionGenerator',
+  STATUS_NOTIFICATION = 'statusNotification',
 }
 
 export interface RequestPayload extends JsonObject {
index ca3d42704f4bfea8b3049b82b6a11dfd2ce6abe3..f235200c283b0393e900754b19e93d9e26f377fc 100644 (file)
@@ -16,6 +16,7 @@ export enum BroadcastChannelProcedureName {
   STOP_TRANSACTION = 'stopTransaction',
   START_AUTOMATIC_TRANSACTION_GENERATOR = 'startAutomaticTransactionGenerator',
   STOP_AUTOMATIC_TRANSACTION_GENERATOR = 'stopAutomaticTransactionGenerator',
+  STATUS_NOTIFICATION = 'statusNotification',
 }
 
 export interface BroadcastChannelRequestPayload extends RequestPayload {
@@ -24,7 +25,8 @@ export interface BroadcastChannelRequestPayload extends RequestPayload {
   idTag?: string;
 }
 
-export interface BroadcastChannelResponsePayload extends ResponsePayload {
+export interface BroadcastChannelResponsePayload
+  extends Omit<ResponsePayload, 'hashIdsSucceeded' | 'hashIdsFailed' | 'responsesFailed'> {
   hashId: string;
 }
 
index db0c7edd94ddcda7736ed43a3f99461526e60070..263947c2d46f47d8dc4e0de9077ae75fa963f5ee 100644 (file)
@@ -34,8 +34,8 @@ export interface OCPP16BootNotificationRequest extends JsonObject {
 export interface OCPP16StatusNotificationRequest extends JsonObject {
   connectorId: number;
   errorCode: OCPP16ChargePointErrorCode;
-  info?: string;
   status: OCPP16ChargePointStatus;
+  info?: string;
   timestamp?: string;
   vendorId?: string;
   vendorErrorCode?: string;