Authorize Request added
authorJakob <jakob-ingenfeld@gmx.de>
Wed, 20 Jan 2021 15:54:37 +0000 (16:54 +0100)
committerJakob <jakob-ingenfeld@gmx.de>
Wed, 20 Jan 2021 15:54:37 +0000 (16:54 +0100)
src/charging-station/AutomaticTransactionGenerator.ts
src/charging-station/ChargingStation.ts
src/types/ocpp/1.6/Requests.ts
src/types/ocpp/1.6/Transaction.ts

index 0b1e7e2786d7f31c41f6be853c80d651b79e4db0..363605be0e8a19d8d57718c2e3a33a1fe58ae3d0 100644 (file)
@@ -97,7 +97,7 @@ export default class AutomaticTransactionGenerator {
         } else {
           startResponse = await this.startTransaction(connectorId, this);
         }
-        if (startResponse.idTagInfo.status !== AuthorizationStatus.ACCEPTED) {
+        if (startResponse?.idTagInfo?.status !== AuthorizationStatus.ACCEPTED) {
           logger.info(this._logPrefix(connectorId) + ' transaction rejected');
           await Utils.sleep(Constants.CHARGING_STATION_ATG_WAIT_TIME);
         } else {
@@ -131,7 +131,14 @@ export default class AutomaticTransactionGenerator {
     if (self._chargingStation.hasAuthorizedTags()) {
       const tagId = self._chargingStation.getRandomTagId();
       logger.info(self._logPrefix(connectorId) + ' start transaction for tagID ' + tagId);
-      return await self._chargingStation.sendStartTransaction(connectorId, tagId);
+      // Authorize tagId
+      const authorizeResponse = await self._chargingStation.sendAuthorize(tagId);
+      if (authorizeResponse?.idTagInfo?.status === AuthorizationStatus.ACCEPTED) {
+        // Start transaction
+        return await self._chargingStation.sendStartTransaction(connectorId, tagId);
+      } else {
+        return authorizeResponse as StartTransactionResponse;
+      }
     }
     logger.info(self._logPrefix(connectorId) + ' start transaction without a tagID');
     return await self._chargingStation.sendStartTransaction(connectorId);
index 6870c1f79f2802fec10f002bff3a2fe560090a21..b8ac0233f8abb66ff4c17d4e0da0ad803eaab2c0 100644 (file)
@@ -1,4 +1,4 @@
-import { AuthorizationStatus, StartTransactionRequest, StartTransactionResponse, StopTransactionReason, StopTransactionRequest, StopTransactionResponse } from '../types/ocpp/1.6/Transaction';
+import { AuthorizationStatus, AuthorizeRequest, AuthorizeResponse, StartTransactionRequest, StartTransactionResponse, StopTransactionReason, StopTransactionRequest, StopTransactionResponse } from '../types/ocpp/1.6/Transaction';
 import { AvailabilityType, BootNotificationRequest, ChangeAvailabilityRequest, ChangeConfigurationRequest, GetConfigurationRequest, HeartbeatRequest, IncomingRequestCommand, RemoteStartTransactionRequest, RemoteStopTransactionRequest, RequestCommand, ResetRequest, SetChargingProfileRequest, StatusNotificationRequest, UnlockConnectorRequest } from '../types/ocpp/1.6/Requests';
 import { BootNotificationResponse, ChangeAvailabilityResponse, ChangeConfigurationResponse, DefaultResponse, GetConfigurationResponse, HeartbeatResponse, RegistrationStatus, SetChargingProfileResponse, StatusNotificationResponse, UnlockConnectorResponse } from '../types/ocpp/1.6/RequestResponses';
 import { ChargingProfile, ChargingProfilePurposeType } from '../types/ocpp/1.6/ChargingProfile';
@@ -71,7 +71,13 @@ export default class ChargingStation {
   }
 
   _getStationName(stationTemplate: ChargingStationTemplate): string {
-    return stationTemplate.fixedName ? stationTemplate.baseName : stationTemplate.baseName + '-' + ('000000000' + this._index.toString()).substr(('000000000' + this._index.toString()).length - 4);
+    // In case of multiple instances: add instance index to charging station id
+    let instanceIndex = process.env.CF_INSTANCE_INDEX ? process.env.CF_INSTANCE_INDEX : 0;
+    instanceIndex = instanceIndex > 0 ? instanceIndex : '';
+
+    const idSuffix = Configuration.getChargingStationIdSuffix();
+
+    return stationTemplate.fixedName ? stationTemplate.baseName : stationTemplate.baseName + '-' + instanceIndex + ('000000000' + this._index.toString()).substr(('000000000' + this._index.toString()).length - 4) + idSuffix;
   }
 
   _buildStationInfo(): ChargingStationInfo {
@@ -521,8 +527,7 @@ export default class ChargingStation {
   }
 
   _startAuthorizationFileMonitoring(): void {
-    // eslint-disable-next-line @typescript-eslint/no-unused-vars
-    fs.watchFile(this._getAuthorizationFile(), (current, previous) => {
+    fs.watch(this._getAuthorizationFile()).on("change", e => {
       try {
         logger.debug(this._logPrefix() + ' Authorization file ' + this._getAuthorizationFile() + ' have changed, reload');
         // Initialize _authorizedTags
@@ -534,16 +539,25 @@ export default class ChargingStation {
   }
 
   _startStationTemplateFileMonitoring(): void {
-    // eslint-disable-next-line @typescript-eslint/no-unused-vars
-    fs.watchFile(this._stationTemplateFile, (current, previous) => {
+    fs.watch(this._stationTemplateFile).on("change", e => {
       try {
         logger.debug(this._logPrefix() + ' Template file ' + this._stationTemplateFile + ' have changed, reload');
         // Initialize
         this._initialize();
+        // Stop the ATG
         if (!this._stationInfo.AutomaticTransactionGenerator.enable &&
           this._automaticTransactionGeneration) {
           this._automaticTransactionGeneration.stop().catch(() => { });
         }
+        // Start the ATG
+        if (this._stationInfo.AutomaticTransactionGenerator.enable) {
+          if (!this._automaticTransactionGeneration) {
+            this._automaticTransactionGeneration = new AutomaticTransactionGenerator(this);
+          }
+          if (this._automaticTransactionGeneration.timeToStop) {
+            this._automaticTransactionGeneration.start();
+          }
+        }
         // FIXME?: restart heartbeat and WebSocket ping when their interval values have changed
       } catch (error) {
         logger.error(this._logPrefix() + ' Charging station template file monitoring error: %j', error);
@@ -811,6 +825,17 @@ export default class ChargingStation {
     }
   }
 
+  async sendAuthorize(idTag?: string): Promise<AuthorizeResponse> {
+    try {
+      const payload: AuthorizeRequest = {
+        ...!Utils.isUndefined(idTag) ? { idTag } : { idTag: Constants.TRANSACTION_DEFAULT_IDTAG },
+      };
+      return await this.sendMessage(Utils.generateUUID(), payload, MessageType.CALL_MESSAGE, RequestCommand.AUTHORIZE) as AuthorizeResponse;
+    } catch (error) {
+      this.handleRequestError(RequestCommand.AUTHORIZE, error);
+    }
+  }
+
   async sendStartTransaction(connectorId: number, idTag?: string): Promise<StartTransactionResponse> {
     try {
       const payload: StartTransactionRequest = {
index 1b3e25695f3285da980a57bb24abf5311eb64422..e7e662233aecb7ff6d4176111fd213aeaad30d37 100644 (file)
@@ -8,6 +8,7 @@ export enum RequestCommand {
   HEARTBEAT = 'Heartbeat',
   STATUS_NOTIFICATION = 'StatusNotification',
   CHANGE_CONFIGURATION = 'ChangeConfiguration',
+  AUTHORIZE = 'Authorize',
   START_TRANSACTION = 'StartTransaction',
   STOP_TRANSACTION = 'StopTransaction',
   METERVALUES = 'MeterValues'
index 7b072e700155d5f44bc888888e5d523938d7ceff..22fb6080efadc697771178715dbd86b69cf81ae2 100644 (file)
@@ -29,6 +29,14 @@ export interface IdTagInfo {
   expiryDate?: Date;
 }
 
+export interface AuthorizeRequest {
+  idTag: string;
+
+}
+export interface AuthorizeResponse {
+  idTagInfo: IdTagInfo;
+}
+
 export interface StartTransactionRequest {
   connectorId: number;
   idTag: string;