Add opening times in SLF. Use CPO local Transaction ID in OCPI Session ID and CDR ID
MODIFY
src/client/ocpi/CpoOCPIClient.ts
src/client/ocpi/CpoOCPIClient.ts
@@ -228,7 +228,7 @@ export default class CpoOCPIClient extends OCPIClient {
transaction.connectorId, this.getLocalCountryCode(ServerAction.OCPI_PUSH_SESSIONS), this.getLocalPartyID(ServerAction.OCPI_PUSH_SESSIONS));
// Build payload
const ocpiSession: OCPISession = {
- id: authorizationId,
+ id: transaction.id.toString(),
start_datetime: transaction.timestamp,
kwh: 0,
auth_method: OCPIAuthMethod.AUTH_REQUEST,

MODIFY
src/server/ocpi/ocpi-services-impl/ocpi-2.1.1/OCPIUtilsService.ts
src/server/ocpi/ocpi-services-impl/ocpi-2.1.1/OCPIUtilsService.ts
import ChargingStation, { ChargePoint, Connector, ConnectorType, CurrentType, Voltage } from '../../../../types/ChargingStation';
import { OCPICapability, OCPIEvse, OCPIEvseStatus } from '../../../../types/ocpi/OCPIEvse';
import { OCPIConnector, OCPIConnectorFormat, OCPIConnectorType, OCPIPowerType, OCPIVoltage } from '../../../../types/ocpi/OCPIConnector';
-import { OCPILocation, OCPILocationOptions, OCPILocationType } from '../../../../types/ocpi/OCPILocation';
+import { OCPILocation, OCPILocationOptions, OCPILocationType, OCPIOpeningTimes } from '../../../../types/ocpi/OCPILocation';
import { OCPISession, OCPISessionStatus } from '../../../../types/ocpi/OCPISession';
import { OCPITariff, OCPITariffDimensionType } from '../../../../types/ocpi/OCPITariff';
import { OCPIToken, OCPITokenWhitelist } from '../../../../types/ocpi/OCPIToken';
@@ -187,9 +187,7 @@ export default class OCPIUtilsService {
evses: withChargingStations ?
await OCPIUtilsService.getEvsesFromSite(tenant, site.id, options, Constants.DB_PARAMS_MAX_LIMIT) : [],
last_updated: site.lastChangedOn ? site.lastChangedOn : site.createdOn,
- opening_times: {
- twentyfourseven: true,
- }
+ opening_times: this.buildOpeningHours(tenant, site)
};
}
@@ -944,4 +942,49 @@ export default class OCPIUtilsService {
}
}
}
+
+ // TODO: Implement the Opening Hours in the Site and send it to OCPI
+ private static buildOpeningHours(tenant: Tenant, site: Site): OCPIOpeningTimes {
+ switch (tenant?.id) {
+ // SLF
+ case '5be7fb271014d90008992f06':
+ // Mougins
+ switch (site.id) {
+ case '5abeba8d4bae1457eb565e5b':
+ return {
+ regular_hours: [
+ {
+ weekday: 1, // Monday
+ period_begin: '08:00',
+ period_end: '18:00'
+ },
+ {
+ weekday: 2,
+ period_begin: '08:00',
+ period_end: '18:00'
+ },
+ {
+ weekday: 3,
+ period_begin: '08:00',
+ period_end: '18:00'
+ },
+ {
+ weekday: 4,
+ period_begin: '08:00',
+ period_end: '18:00'
+ },
+ {
+ weekday: 5,
+ period_begin: '08:00',
+ period_end: '18:00'
+ },
+ ]
+ };
+ }
+ }
+ // Default
+ return {
+ twentyfourseven: true,
+ };
+ }
}

MODIFY
src/server/ocpp/services/OCPPService.ts
src/server/ocpp/services/OCPPService.ts
@@ -665,6 +665,7 @@ export default class OCPPService {
headers.tenantID, chargingStation.id, startTransaction.connectorId);
// Create
const transaction: Transaction = {
+ id: await TransactionStorage.findAvailableID(tenant.id),
issuer: true,
chargeBoxID: startTransaction.chargeBoxID,
tagID: startTransaction.idTag,
@@ -730,7 +731,6 @@ export default class OCPPService {
if (transaction.user && !transaction.user.issuer) {
// Assumption: Either Gireve or Hubject is enabled for eRoaming
// OCPI or OICP
- // TODO: OCPI and OICP must work together and then the IOP must be identified clearly to call the right implementation
if (Utils.isTenantComponentActive(tenant, TenantComponents.OCPI)) {
// OCPI
await OCPPUtils.processOCPITransaction(headers.tenantID, transaction, chargingStation, TransactionAction.START);
@@ -740,7 +740,7 @@ export default class OCPPService {
}
}
// Save it
- transaction.id = await TransactionStorage.saveTransaction(headers.tenantID, transaction);
+ await TransactionStorage.saveTransaction(headers.tenantID, transaction);
// Clean up Charging Station's connector transaction info
const foundConnector = Utils.getConnectorFromID(chargingStation, transaction.connectorId);
if (foundConnector) {

MODIFY
src/server/ocpp/utils/OCPPUtils.ts
src/server/ocpp/utils/OCPPUtils.ts
@@ -120,7 +120,7 @@ export default class OCPPUtils {
for (const authorization of authorizations.result) {
if (authorization.authorizationId) {
// OCPI authorizationId = OCPI sessionID
- const ocpiTransaction = await TransactionStorage.getOCPITransactionBySessionID(tenant.id, authorization.authorizationId);
+ const ocpiTransaction = await TransactionStorage.getOCPITransactionByAuthorizationID(tenant.id, authorization.authorizationId);
// OCPI ID not used yet
if (!ocpiTransaction) {
authorizationId = authorization.authorizationId;

MODIFY
src/storage/mongodb/TransactionStorage.ts
src/storage/mongodb/TransactionStorage.ts
@@ -46,7 +46,7 @@ export default class TransactionStorage {
await DatabaseUtils.checkTenant(tenantID);
// ID not provided?
if (!transactionToSave.id) {
- transactionToSave.id = await TransactionStorage._findAvailableID(tenantID);
+ transactionToSave.id = await TransactionStorage.findAvailableID(tenantID);
}
// Transfer
const transactionMDB: any = {
@@ -269,7 +269,7 @@ export default class TransactionStorage {
transactionIDs?: number[]; issuer?: boolean; search?: string; ownerID?: string; userIDs?: string[]; siteAdminIDs?: string[];
chargeBoxIDs?: string[]; siteAreaIDs?: string[]; siteIDs?: string[]; connectorIDs?: number[]; startDateTime?: Date;
endDateTime?: Date; stop?: any; minimalPrice?: boolean; reportIDs?: string[]; tagIDs?: string[]; inactivityStatus?: string[];
- ocpiSessionID?: string; ocpiSessionDateFrom?: Date; ocpiSessionDateTo?: Date; ocpiCdrDateFrom?: Date; ocpiCdrDateTo?: Date;
+ ocpiSessionID?: string; ocpiAuthorizationID?: string; ocpiSessionDateFrom?: Date; ocpiSessionDateTo?: Date; ocpiCdrDateFrom?: Date; ocpiCdrDateTo?: Date;
ocpiSessionChecked?: boolean; ocpiCdrChecked?: boolean; oicpSessionID?: string;
statistics?: 'refund' | 'history'; refundStatus?: string[]; withTag?: boolean; hasUserID?: boolean;
},
@@ -314,16 +314,19 @@ export default class TransactionStorage {
{ '_id': Utils.convertToInt(params.search) },
{ 'tagID': { $regex: params.search, $options: 'i' } },
{ 'chargeBoxID': { $regex: params.search, $options: 'i' } },
- { 'ocpiData.session.id': { $regex: params.search, $options: 'i' } }
+ { 'ocpiData.session.authorization_id': { $regex: params.search, $options: 'i' } }
];
}
// OCPI ID
if (params.ocpiSessionID) {
filters['ocpiData.session.id'] = params.ocpiSessionID;
}
+ if (params.ocpiAuthorizationID) {
+ filters['ocpiData.session.authorization_id'] = params.ocpiAuthorizationID;
+ }
// OICP ID
if (params.oicpSessionID) {
- filters['oicpData.session.id'] = params.oicpSessionID;
+ filters['oicpData.session.SessionID'] = params.oicpSessionID;
}
// Transaction
if (!Utils.isEmptyArray(params.transactionIDs)) {
@@ -973,6 +976,12 @@ export default class TransactionStorage {
return transactionsMDB.count === 1 ? transactionsMDB.result[0] : null;
}
+ public static async getOCPITransactionByAuthorizationID(tenantID: string, authorizationID: string): Promise<Transaction> {
+ const transactionsMDB = await TransactionStorage.getTransactions(tenantID,
+ { ocpiAuthorizationID: authorizationID }, Constants.DB_PARAMS_SINGLE_RECORD);
+ return transactionsMDB.count === 1 ? transactionsMDB.result[0] : null;
+ }
+
public static async getOICPTransactionBySessionID(tenantID: string, sessionID: string): Promise<Transaction> {
const transactionsMDB = await TransactionStorage.getTransactions(tenantID,
{ oicpSessionID: sessionID }, Constants.DB_PARAMS_SINGLE_RECORD);
@@ -1077,7 +1086,7 @@ export default class TransactionStorage {
return transactionsMDB.length === 1 ? transactionsMDB[0] : null;
}
- public static async _findAvailableID(tenantID: string): Promise<number> {
+ public static async findAvailableID(tenantID: string): Promise<number> {
// Debug
const uniqueTimerID = Logging.traceStart(tenantID, MODULE_NAME, '_findAvailableID');
// Check

MODIFY
src/types/ocpi/OCPILocation.ts
src/types/ocpi/OCPILocation.ts
@@ -28,14 +28,16 @@ export interface OCPILocation {
evses: OCPIEvse[];
last_updated: Date;
// OCPI specify that attribute as optional but Gireve requires it
- opening_times: {
+ opening_times: OCPIOpeningTimes;
+ charging_when_closed?: boolean;
+}
+
+export interface OCPIOpeningTimes {
regular_hours?: OCPIDayPeriod[];
- twentyfourseven: boolean;
+ twentyfourseven?: boolean;
exceptional_openings?: OCPIPeriod[];
exceptional_closings?: OCPIPeriod[];
}
- charging_when_closed?: boolean;
-}
export enum OCPILocationType {
ON_STREET = 'ON_STREET',

Add opening times in SLF. Use CPO local Transaction ID in OCPI Session ID and CDR ID