Go through Sites to push the EVSEs to Hubject
MODIFY
src/client/oicp/CpoOICPClient.ts
src/client/oicp/CpoOICPClient.ts
@@ -29,8 +29,10 @@ import { OICPRole } from '../../types/oicp/OICPRole';
import OICPUtils from '../../server/oicp/OICPUtils';
import { OicpSetting } from '../../types/Setting';
import { ServerAction } from '../../types/Server';
+import Site from '../../types/Site';
import SiteArea from '../../types/SiteArea';
import SiteAreaStorage from '../../storage/mongodb/SiteAreaStorage';
+import SiteStorage from '../../storage/mongodb/SiteStorage';
import { StatusCodes } from 'http-status-codes';
import Tenant from '../../types/Tenant';
import Utils from '../../utils/Utils';
@@ -52,18 +54,23 @@ export default class CpoOICPClient extends OICPClient {
public async startSession(chargingStation: ChargingStation, transaction: Transaction,
sessionId: OICPSessionID, identification: OICPIdentification): Promise<void> {
+ const options: OCPILocationOptions = {
+ countryID: this.getLocalCountryCode(ServerAction.OICP_PUSH_SESSIONS),
+ partyID: this.getLocalPartyID(ServerAction.OICP_PUSH_SESSIONS),
+ addChargeBoxID: true
+ };
+ // Get Site Area
let siteArea: SiteArea;
if (!chargingStation.siteArea) {
siteArea = await SiteAreaStorage.getSiteArea(this.tenant.id, chargingStation.siteAreaID);
} else {
siteArea = chargingStation.siteArea;
}
- const options: OCPILocationOptions = {
- countryID: this.getLocalCountryCode(ServerAction.OICP_PUSH_SESSIONS),
- partyID: this.getLocalPartyID(ServerAction.OICP_PUSH_SESSIONS),
- addChargeBoxID: true
- };
- const oicpEvse = OICPUtils.getEvseByConnectorId(this.tenant, siteArea, chargingStation, transaction.connectorId, options);
+ // Get Site
+ const site = await SiteStorage.getSite(this.tenant.id, chargingStation.siteID);
+ // Get Evse
+ const oicpEvse = OICPUtils.getEvseByConnectorId(
+ site, siteArea, chargingStation, transaction.connectorId, options);
const oicpSession = {
id: sessionId,
start_datetime: transaction.timestamp,
@@ -76,6 +83,7 @@ export default class CpoOICPClient extends OICPClient {
last_updated: transaction.timestamp,
meterValueInBetween: [],
} as OICPSession;
+ // Set OICP data
transaction.oicpData = {
session: oicpSession
};
@@ -230,15 +238,23 @@ export default class CpoOICPClient extends OICPClient {
};
// Get timestamp before starting process - to be saved in DB at the end of the process
const startDate = new Date();
+ let sites: Site[];
+ let currentSiteSkip = 0;
+ do {
+ // Get the public Sites
+ sites = (await SiteStorage.getSites(this.tenant.id,
+ { public: true }, { skip: currentSiteSkip, limit: Constants.DB_RECORD_COUNT_DEFAULT })).result;
+ if (!Utils.isEmptyArray(sites)) {
+ for (const site of sites) {
let chargingStations: ChargingStation[];
- let currentSkip = 0;
+ let currentChargingStationSkip = 0;
do {
// Get all charging stations from tenant
chargingStations = (await ChargingStationStorage.getChargingStations(this.tenant.id,
- { public: true }, { skip: currentSkip, limit: Constants.DB_RECORD_COUNT_DEFAULT })).result;
+ { siteIDs: [site.id], public: true }, { skip: currentChargingStationSkip, limit: Constants.DB_RECORD_COUNT_DEFAULT })).result;
if (!Utils.isEmptyArray(chargingStations)) {
// Convert (public) charging stations to OICP EVSEs
- const evses = await OICPUtils.convertChargingStationsToEVSEs(this.tenant, chargingStations, options);
+ const evses = await OICPUtils.convertChargingStationsToEVSEs(this.tenant, site, chargingStations, options);
let evsesToProcess: OICPEvseDataRecord[] = [];
let chargeBoxIDsToProcessFromInput = [];
// Check if all EVSEs should be processed - in case of delta send - process only following EVSEs:
@@ -296,8 +312,12 @@ export default class CpoOICPClient extends OICPClient {
} while (!Utils.isEmptyArray(evsesToProcess));
}
}
- currentSkip += Constants.DB_RECORD_COUNT_DEFAULT;
+ currentChargingStationSkip += Constants.DB_RECORD_COUNT_DEFAULT;
} while (!Utils.isEmptyArray(chargingStations));
+ }
+ }
+ currentSiteSkip += Constants.DB_RECORD_COUNT_DEFAULT;
+ } while (!Utils.isEmptyArray(sites));
// Send notification to admins
if (result.failure > 0) {
// eslint-disable-next-line @typescript-eslint/no-floating-promises

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
@@ -117,7 +117,7 @@ export default class OCPIUtilsService {
const ocpiLocationsResult: DataResult<OCPILocation> = { count: 0, result: [] };
// Get all sites
const sites = await SiteStorage.getSites(tenant.id,
- { issuer: true, onlyPublicSite: true },
+ { issuer: true, public: true },
limit === 0 ? Constants.DB_PARAMS_MAX_LIMIT : { limit, skip },
['id', 'name', 'address', 'lastChangedOn', 'createdOn']);
// Convert Sites to Locations
@@ -128,7 +128,7 @@ export default class OCPIUtilsService {
let nbrOfSites = sites.count;
if (nbrOfSites === -1) {
const sitesCount = await SiteStorage.getSites(tenant.id,
- { issuer: true, onlyPublicSite: true }, Constants.DB_PARAMS_COUNT_ONLY);
+ { issuer: true, public: true }, Constants.DB_PARAMS_COUNT_ONLY);
nbrOfSites = sitesCount.count;
}
// Set count

MODIFY
src/server/oicp/OICPUtils.ts
src/server/oicp/OICPUtils.ts
@@ -15,6 +15,7 @@ import { OICPSession } from '../../types/oicp/OICPSession';
import { OICPStatusCode } from '../../types/oicp/OICPStatusCode';
import RoamingUtils from '../../utils/RoamingUtils';
import { ServerAction } from '../../types/Server';
+import Site from '../../types/Site';
import SiteArea from '../../types/SiteArea';
import Tenant from '../../types/Tenant';
import Transaction from '../../types/Transaction';
@@ -27,13 +28,13 @@ import moment from 'moment';
const MODULE_NAME = 'OICPUtils';
export default class OICPUtils {
- public static getEvseByConnectorId(tenant: Tenant, siteArea: SiteArea, chargingStation: ChargingStation, connectorId: number,
+ public static getEvseByConnectorId(site: Site, siteArea: SiteArea, chargingStation: ChargingStation, connectorId: number,
options: { countryID: string; partyID: string; addChargeBoxID?: boolean}): OICPEvseDataRecord {
// Loop through connectors and send one evse per connector
const foundConnector = chargingStation.connectors.find(
(connector) => connector?.connectorId === connectorId);
if (foundConnector) {
- return OICPUtils.convertConnector2Evse(siteArea, chargingStation, foundConnector, options);
+ return OICPUtils.convertConnector2Evse(site, siteArea, chargingStation, foundConnector, options);
}
return null;
}
@@ -47,13 +48,13 @@ export default class OICPUtils {
};
}
- public static async convertChargingStationsToEVSEs(tenant: Tenant, chargingStations: ChargingStation[],
+ public static async convertChargingStationsToEVSEs(tenant: Tenant, site: Site, chargingStations: ChargingStation[],
options: { countryID: string; partyID: string; addChargeBoxID?: boolean }): Promise<OICPEvseDataRecord[]> {
const evses: OICPEvseDataRecord[] = [];
// Convert charging stations to evse(s)
for (const chargingStation of chargingStations) {
if (chargingStation.issuer && chargingStation.public) {
- const chargingStationEvses = OICPUtils.convertChargingStation2MultipleEvses(chargingStation.siteArea, chargingStation, options);
+ const chargingStationEvses = OICPUtils.convertChargingStation2MultipleEvses(site, chargingStation.siteArea, chargingStation, options);
// Update the Charging Station's OICP Data
await ChargingStationStorage.saveChargingStationOicpData(tenant.id, chargingStation.id, {
evses: chargingStationEvses
@@ -76,7 +77,7 @@ export default class OICPUtils {
return evseStatuses;
}
- public static convertChargingStation2MultipleEvses(siteArea: SiteArea, chargingStation: ChargingStation,
+ public static convertChargingStation2MultipleEvses(site: Site, siteArea: SiteArea, chargingStation: ChargingStation,
options: { countryID: string; partyID: string; addChargeBoxID?: boolean}): OICPEvseDataRecord[] {
let connectors: Connector[] = [];
if (!Utils.isEmptyArray(chargingStation.chargePoints)) {
@@ -88,8 +89,9 @@ export default class OICPUtils {
} else {
connectors = chargingStation.connectors.filter((connector) => connector !== null);
}
+ // Convert Connectors to Chargepoint EVSEs
const evses = connectors.map(
- (connector) => OICPUtils.convertConnector2Evse(siteArea, chargingStation, connector, options));
+ (connector) => OICPUtils.convertConnector2Evse(site, siteArea, chargingStation, connector, options));
return evses;
}
@@ -296,12 +298,12 @@ export default class OICPUtils {
}
}
- private static getOICPAddressIso19773FromSiteArea(siteArea: SiteArea, countryID: string): OICPAddressIso19773 {
+ private static getOICPAddressIso19773FromSiteArea(site: Site, siteArea: SiteArea, countryID: string): OICPAddressIso19773 {
let address: Address;
if (siteArea.address) {
address = siteArea.address;
} else {
- address = siteArea.site.address;
+ address = site.address;
}
return {
Country: OICPUtils.convertCountry2CountryCode(address.country, countryID), // OICP expects Alpha-3 county code.
@@ -408,7 +410,7 @@ export default class OICPUtils {
return evseStatuses;
}
- private static convertConnector2Evse(siteArea: SiteArea, chargingStation: ChargingStation, connector: Connector,
+ private static convertConnector2Evse(site: Site, siteArea: SiteArea, chargingStation: ChargingStation, connector: Connector,
options: { countryID: string; partyID: string; addChargeBoxID?: boolean}): OICPEvseDataRecord {
const evse: OICPEvseDataRecord = {} as OICPEvseDataRecord;
evse.deltaType; // Optional
@@ -425,7 +427,7 @@ export default class OICPUtils {
evse.HardwareManufacturer = chargingStation.chargePointVendor; // Optional
evse.ChargingStationImage; // Optional
evse.SubOperatorName; // Optional
- evse.Address = OICPUtils.getOICPAddressIso19773FromSiteArea(siteArea, options.countryID);
+ evse.Address = OICPUtils.getOICPAddressIso19773FromSiteArea(site, siteArea, options.countryID);
evse.GeoCoordinates = OICPUtils.convertCoordinates2OICPGeoCoordinates(chargingStation.coordinates, OICPGeoCoordinatesResponseFormat.DecimalDegree); // Optional
evse.Plugs = [OICPUtils.convertConnector2OICPPlug(connector)];
evse.DynamicPowerLevel; // Optional

MODIFY
src/server/rest/v1/service/ChargingStationService.ts
src/server/rest/v1/service/ChargingStationService.ts
@@ -33,6 +33,7 @@ import OICPUtils from '../../../oicp/OICPUtils';
import { ServerAction } from '../../../../types/Server';
import SiteArea from '../../../../types/SiteArea';
import SiteAreaStorage from '../../../../storage/mongodb/SiteAreaStorage';
+import SiteStorage from '../../../../storage/mongodb/SiteStorage';
import SmartChargingFactory from '../../../../integration/smart-charging/SmartChargingFactory';
import { StatusCodes } from 'http-status-codes';
import Tenant from '../../../../types/Tenant';
@@ -139,8 +140,11 @@ export default class ChargingStationService {
countryID: oicpClient.getLocalCountryCode(ServerAction.OICP_PUSH_EVSE_DATA),
partyID: oicpClient.getLocalPartyID(ServerAction.OICP_PUSH_EVSE_DATA)
};
+ // Get Site
+ const site = await SiteStorage.getSite(req.tenant.id, chargingStation.siteID);
+ // Push EVSE to OICP platform
await oicpClient.pushEvseData(OICPUtils.convertChargingStation2MultipleEvses(
- chargingStation.siteArea, chargingStation, options), actionType);
+ site, chargingStation.siteArea, chargingStation, options), actionType);
}
} catch (error) {
await Logging.logError({
@@ -843,8 +847,11 @@ export default class ChargingStationService {
countryID: oicpClient.getLocalCountryCode(ServerAction.OICP_PUSH_EVSE_DATA),
partyID: oicpClient.getLocalPartyID(ServerAction.OICP_PUSH_EVSE_DATA)
};
+ // Get Site
+ const site = await SiteStorage.getSite(req.tenant.id, chargingStation.siteID);
+ // Push EVSE to OICP platform
await oicpClient.pushEvseData(OICPUtils.convertChargingStation2MultipleEvses(
- chargingStation.siteArea, chargingStation, options), OICPActionType.DELETE);
+ site, chargingStation.siteArea, chargingStation, options), OICPActionType.DELETE);
}
} catch (error) {
await Logging.logError({

MODIFY
src/storage/mongodb/SiteStorage.ts
src/storage/mongodb/SiteStorage.ts
@@ -306,7 +306,7 @@ export default class SiteStorage {
public static async getSites(tenantID: string,
params: {
search?: string; companyIDs?: string[]; withAutoUserAssignment?: boolean; siteIDs?: string[];
- userID?: string; excludeSitesOfUserID?: boolean; issuer?: boolean; onlyPublicSite?: boolean; name?: string;
+ userID?: string; excludeSitesOfUserID?: boolean; issuer?: boolean; public?: boolean; name?: string;
withAvailableChargingStations?: boolean; withOnlyChargingStations?: boolean; withCompany?: boolean;
locCoordinates?: number[]; locMaxDistanceMeters?: number; withImage?: boolean;
} = {},
@@ -365,8 +365,8 @@ export default class SiteStorage {
filters.issuer = params.issuer;
}
// Public Site
- if (params.onlyPublicSite) {
- filters.public = params.onlyPublicSite;
+ if (params.public) {
+ filters.public = params.public;
}
// Auto User Site Assignment
if (params.withAutoUserAssignment) {

Go through Sites to push the EVSEs to Hubject