Fixed OCPI Remote Start creates RFID Card on the fly
MODIFY
src/client/ocpi/CpoOCPIClient.ts
src/client/ocpi/CpoOCPIClient.ts
@@ -125,11 +125,13 @@ export default class CpoOCPIClient extends OCPIClient {
await Promise.map(tokens, async (token) => {
try {
// Get eMSP user
- const email = OCPIUtils.buildEmspEmailFromOCPIToken(token, this.ocpiEndpoint.countryCode, this.ocpiEndpoint.partyId);
+ const email = OCPIUtils.buildEmspEmailFromOCPIToken(
+ token, this.ocpiEndpoint.countryCode, this.ocpiEndpoint.partyId);
const emspUser = emspUsersMap.get(email);
// Get the Tag
const emspTag = tags.result.find((tag) => tag.id === token.uid);
- await OCPIUtilsService.updateCpoToken(this.tenant, token, emspTag, emspUser, ServerAction.OCPI_CPO_GET_TOKENS);
+ await OCPIUtilsService.updateCreateTagWithCpoToken(
+ this.tenant, token, emspTag, emspUser, ServerAction.OCPI_CPO_GET_TOKENS);
result.success++;
} catch (error) {
result.failure++;
@@ -776,7 +778,6 @@ export default class CpoOCPIClient extends OCPIClient {
`{{inSuccess}} EVSE Status(es) were successfully patched and {{inError}} failed to be patched in ${executionDurationSecs}s`,
'No EVSE Status have been patched'
);
- // Return result
return result;
}
@@ -784,34 +785,22 @@ export default class CpoOCPIClient extends OCPIClient {
if (!Utils.isEmptyArray(tokens)) {
for (const token of tokens) {
// Get eMSP user
- const email = OCPIUtils.buildEmspEmailFromOCPIToken(token, this.ocpiEndpoint.countryCode, this.ocpiEndpoint.partyId);
- // Check cache
+ const email = OCPIUtils.buildEmspEmailFromOCPIToken(
+ token, this.ocpiEndpoint.countryCode, this.ocpiEndpoint.partyId);
+ // Check from cache
let emspUser = emspUsers.get(email);
if (!emspUser) {
- // Get User from DB
- emspUser = await UserStorage.getUserByEmail(this.tenant, email);
- // Create user
- if (!emspUser) {
- // Create User
- emspUser = {
- issuer: false,
- createdOn: token.last_updated,
- lastChangedOn: token.last_updated,
- name: token.issuer,
- firstName: OCPIUtils.buildOperatorName(this.ocpiEndpoint.countryCode, this.ocpiEndpoint.partyId),
- email: OCPIUtils.buildEmspEmailFromOCPIToken(token, this.ocpiEndpoint.countryCode, this.ocpiEndpoint.partyId),
- locale: Utils.getLocaleFromLanguage(token.language),
- } as User;
- // Save User
- emspUser.id = await UserStorage.saveUser(this.tenant, emspUser);
- await UserStorage.saveUserRole(this.tenant, emspUser.id, UserRole.BASIC);
- await UserStorage.saveUserStatus(this.tenant, emspUser.id, UserStatus.ACTIVE);
- }
+ // Check eMsp User
+ emspUser = await OCPIUtils.checkAndCreateEMSPUserFromToken(
+ this.tenant, this.ocpiEndpoint.countryCode, this.ocpiEndpoint.partyId, token);
+ if (emspUser) {
+ // Keep in cache
emspUsers.set(email, emspUser);
}
}
}
}
+ }
private async getChargeBoxIDsWithNewStatusNotifications(): Promise<string[]> {
// Get last job

MODIFY
src/server/ocpi/OCPIUtils.ts
src/server/ocpi/OCPIUtils.ts
@@ -4,6 +4,7 @@ import OCPIEndpoint, { OCPIAvailableEndpoints, OCPIEndpointVersions } from '../.
import { OCPIEvse, OCPIEvseStatus } from '../../types/ocpi/OCPIEvse';
import { OCPITariff, OCPITariffDimensionType } from '../../types/ocpi/OCPITariff';
import { OCPIToken, OCPITokenType, OCPITokenWhitelist } from '../../types/ocpi/OCPIToken';
+import User, { UserRole, UserStatus } from '../../types/User';
import AppError from '../../exception/AppError';
import BackendError from '../../exception/BackendError';
@@ -32,7 +33,7 @@ import SiteAreaStorage from '../../storage/mongodb/SiteAreaStorage';
import SiteStorage from '../../storage/mongodb/SiteStorage';
import Tag from '../../types/Tag';
import Tenant from '../../types/Tenant';
-import { UserStatus } from '../../types/User';
+import UserStorage from '../../storage/mongodb/UserStorage';
import Utils from '../../utils/Utils';
import moment from 'moment';
@@ -145,9 +146,32 @@ export default class OCPIUtils {
}
public static buildEmspEmailFromOCPIToken(token: OCPIToken, countryCode: string, partyId: string): string {
- if (token?.issuer) {
return `${token.issuer}@${partyId}.${countryCode}`.toLowerCase();
}
+
+ public static async checkAndCreateEMSPUserFromToken(tenant: Tenant, countryCode: string, partyId: string, token: OCPIToken): Promise<User> {
+ // Get eMSP user
+ const email = OCPIUtils.buildEmspEmailFromOCPIToken(token, countryCode, partyId);
+ // Get User from DB
+ let emspUser = await UserStorage.getUserByEmail(tenant, email);
+ // Create user
+ if (!emspUser) {
+ // Create User
+ emspUser = {
+ issuer: false,
+ createdOn: token.last_updated,
+ lastChangedOn: token.last_updated,
+ name: token.issuer,
+ firstName: OCPIUtils.buildOperatorName(countryCode, partyId),
+ email,
+ locale: Utils.getLocaleFromLanguage(token.language),
+ } as User;
+ // Save User
+ emspUser.id = await UserStorage.saveUser(tenant, emspUser);
+ await UserStorage.saveUserRole(tenant, emspUser.id, UserRole.BASIC);
+ await UserStorage.saveUserStatus(tenant, emspUser.id, UserStatus.ACTIVE);
+ }
+ return emspUser;
}
public static atob(base64: string): string {

MODIFY
src/server/ocpi/service/OCPIUtilsService.ts
src/server/ocpi/service/OCPIUtilsService.ts
@@ -561,7 +561,7 @@ export default class OCPIUtilsService {
await OCPPUtils.updateChargingStationConnectorRuntimeDataWithTransaction(tenant, chargingStation, transaction, true);
}
- public static async updateCpoToken(tenant: Tenant, token: OCPIToken, tag: Tag, emspUser: User, action: ServerAction): Promise<void> {
+ public static async updateCreateTagWithCpoToken(tenant: Tenant, token: OCPIToken, tag: Tag, emspUser: User, action: ServerAction): Promise<Tag> {
if (!OCPIUtilsService.validateCpoToken(token)) {
throw new AppError({
module: MODULE_NAME, method: 'updateCpoToken', action,
@@ -610,12 +610,14 @@ export default class OCPIUtilsService {
active: token.valid === true ? true : false,
description: token.visual_number,
lastChangedOn: token.last_updated,
- ocpiToken: token
+ ocpiToken: token,
+ user: emspUser,
};
// Save Tag
if (!tag || JSON.stringify(tagToSave.ocpiToken) !== JSON.stringify(tag.ocpiToken)) {
await TagStorage.saveTag(tenant, tagToSave);
}
+ return tagToSave;
}
public static convertConnector2OcpiConnector(tenant: Tenant, chargingStation: ChargingStation,

MODIFY
src/server/ocpi/service/cpo/v2.1.1/CPOCommandsService.ts
src/server/ocpi/service/cpo/v2.1.1/CPOCommandsService.ts
@@ -70,7 +70,8 @@ export default class CPOCommandsService {
next();
}
- private static async remoteStartSession(action: ServerAction, req: Request, res: Response, next: NextFunction, tenant: Tenant, ocpiEndpoint: OCPIEndpoint): Promise<OCPIResponse> {
+ private static async remoteStartSession(action: ServerAction, req: Request, res: Response,
+ next: NextFunction, tenant: Tenant, ocpiEndpoint: OCPIEndpoint): Promise<OCPIResponse> {
const startSession = req.body as OCPIStartSession;
if (!CPOCommandsService.validateStartSession(startSession)) {
throw new AppError({
@@ -81,8 +82,15 @@ export default class CPOCommandsService {
ocpiError: OCPIStatusCode.CODE_2001_INVALID_PARAMETER_ERROR
});
}
- const localToken = await TagStorage.getTag(
+ let localToken = await TagStorage.getTag(
tenant, startSession.token.uid, { withUser: true });
+ // Create it on the fly
+ if (!localToken) {
+ // Check eMSP user
+ const emspUser = await OCPIUtils.checkAndCreateEMSPUserFromToken(
+ tenant, ocpiEndpoint.countryCode, ocpiEndpoint.partyId, startSession.token);
+ localToken = await OCPIUtilsService.updateCreateTagWithCpoToken(tenant, startSession.token, localToken, emspUser, action);
+ }
if (!localToken?.active || !localToken.ocpiToken?.valid) {
await Logging.logError({
tenantID: tenant.id,

MODIFY
src/server/ocpi/service/cpo/v2.1.1/CPOTokensService.ts
src/server/ocpi/service/cpo/v2.1.1/CPOTokensService.ts
@@ -109,7 +109,7 @@ export default class CPOTokensService {
detailedMessages: { operator, token, tag }
});
}
- await OCPIUtilsService.updateCpoToken(tenant, token, tag, tag.user, ServerAction.OCPI_CPO_UPDATE_TOKEN);
+ await OCPIUtilsService.updateCreateTagWithCpoToken(tenant, token, tag, tag.user, ServerAction.OCPI_CPO_UPDATE_TOKEN);
res.json(OCPIUtils.success());
next();
}

Fixed OCPI Remote Start creates RFID Card on the fly