Fixed/Typed Unit Tests + Add logs in offline charger task
MODIFY
src/scheduler/tasks/CheckOfflineChargingStationsTask.ts
src/scheduler/tasks/CheckOfflineChargingStationsTask.ts
@@ -13,8 +13,9 @@ import Tenant from '../../types/Tenant';
import Utils from '../../utils/Utils';
import moment from 'moment';
-export default class CheckOfflineChargingStationsTask extends SchedulerTask {
+const MODULE_NAME = 'CheckOfflineChargingStationsTask';
+export default class CheckOfflineChargingStationsTask extends SchedulerTask {
async processTenant(tenant: Tenant, config: CheckOfflineChargingStationsTaskConfig): Promise<void> {
// Get the lock
const offlineChargingStationLock = LockingManager.createExclusiveLock(tenant.id, LockEntity.CHARGING_STATION, 'offline-charging-station');

MODIFY
src/utils/Logging.ts
src/utils/Logging.ts
import { AxiosError, AxiosRequestConfig, AxiosResponse } from 'axios';
-import CFLog from 'cf-nodejs-logging-support';
-import cfenv from 'cfenv';
-import cluster from 'cluster';
+import { Log, LogLevel, LogType } from '../types/Log';
import { NextFunction, Request, Response } from 'express';
-import jwtDecode from 'jwt-decode';
-import os from 'os';
import { PerformanceObserver, performance } from 'perf_hooks';
-import { v4 as uuid } from 'uuid';
+
import AppAuthError from '../exception/AppAuthError';
import AppError from '../exception/AppError';
import BackendError from '../exception/BackendError';
-import LoggingStorage from '../storage/mongodb/LoggingStorage';
-import TenantStorage from '../storage/mongodb/TenantStorage';
+import CFLog from 'cf-nodejs-logging-support';
+import Configuration from '../utils/Configuration';
+import Constants from './Constants';
import { HTTPError } from '../types/HTTPError';
-import { Log, LogLevel, LogType } from '../types/Log';
+import LoggingStorage from '../storage/mongodb/LoggingStorage';
import { ServerAction } from '../types/Server';
+import TenantStorage from '../storage/mongodb/TenantStorage';
import User from '../types/User';
import UserToken from '../types/UserToken';
-import Configuration from '../utils/Configuration';
-import Constants from './Constants';
import Utils from './Utils';
-
+import cfenv from 'cfenv';
+import cluster from 'cluster';
+import jwtDecode from 'jwt-decode';
+import os from 'os';
+import { v4 as uuid } from 'uuid';
const _loggingConfig = Configuration.getLoggingConfig();
let _traceStatistics = null;
@@ -282,10 +282,10 @@ export default class Logging {
module: MODULE_NAME, method: 'interceptor',
detailedMessages: {
url: error.config.url,
- status: error.response.status,
- statusText: error.response.statusText,
+ status: error.response?.status,
+ statusText: error.response?.statusText,
message: error.message,
- response: error.response.data,
+ response: error.response?.data,
axiosError: error.toJSON(),
}
});

MODIFY
test/api/OCPPCommonTests.ts
test/api/OCPPCommonTests.ts
@@ -326,8 +326,6 @@ export default class OCPPCommonTests {
'vendorId': 'Schneider Electric',
'messageId': 'Detection loop',
'data': '{\\"connectorId\\":2,\\"name\\":\\"Vehicle\\",\\"state\\":\\"0\\",\\"timestamp\\":\\"2018-08-08T10:21:11Z:\\"}',
- 'chargeBoxID': this.chargingStationContext.getChargingStation().id,
- 'timestamp': new Date().toDateString()
});
// Check
expect(response).to.have.property('status');

MODIFY
test/api/TransactionCommonTests.ts
test/api/TransactionCommonTests.ts
+import Transaction, { InactivityStatus } from '../../src/types/Transaction';
import chai, { expect } from 'chai';
import CentralServerService from './client/CentralServerService';
import ChargingStationContext from './context/ChargingStationContext';
-import { InactivityStatus } from '../../src/types/Transaction';
import TenantContext from './context/TenantContext';
import TestUtils from './TestUtils';
import User from '../../src/types/User';
@@ -592,6 +592,9 @@ export default class TransactionCommonTests {
);
expect(meterValueResponse).to.eql({});
}
+ const transactionResponse = await this.transactionUserService.transactionApi.readById(transactionId);
+ expect(transactionResponse.status).to.equal(200);
+ const transaction = transactionResponse.data as Transaction;
const consumptions = await this.transactionUserService.transactionApi.readAllConsumption(
{ TransactionId: transactionId });
expect(consumptions.status).to.equal(200);
@@ -599,7 +602,7 @@ export default class TransactionCommonTests {
id: transactionId,
values: [
{
- date: meterValues[0].timestamp.toISOString(),
+ date: transaction.timestamp,
instantWatts: meterValues[0].value,
instantAmps: Utils.convertWattToAmp(
this.chargingStationContext.getChargingStation(), null, connectorId, meterValues[0].value),
@@ -608,7 +611,7 @@ export default class TransactionCommonTests {
this.chargingStationContext.getChargingStation(), null, connectorId, meterValues[0].value),
},
{
- date: meterValues[1].timestamp.toISOString(),
+ date: meterValues[0].timestamp.toISOString(),
instantWatts: meterValues[1].value,
instantAmps: Utils.convertWattToAmp(
this.chargingStationContext.getChargingStation(), null, connectorId, meterValues[1].value),

MODIFY
test/api/context/ChargingStationContext.ts
test/api/context/ChargingStationContext.ts
-import { ChargePointErrorCode, ChargePointStatus, OCPP15MeterValuesRequest, OCPP15TransactionData, OCPPAuthorizeResponse, OCPPBootNotificationResponse, OCPPDataTransferResponse, OCPPFirmwareStatus, OCPPFirmwareStatusNotificationResponse, OCPPHeartbeatResponse, OCPPLocation, OCPPMeasurand, OCPPMeterValue, OCPPMeterValuesRequest, OCPPMeterValuesResponse, OCPPReadingContext, OCPPStartTransactionResponse, OCPPStatusNotificationRequest, OCPPStatusNotificationResponse, OCPPStopTransactionResponse, OCPPUnitOfMeasure, OCPPValueFormat, OCPPVersion } from '../../../src/types/ocpp/OCPPServer';
+import { ChargePointErrorCode, ChargePointStatus, OCPP15MeterValuesRequest, OCPP15TransactionData, OCPPAuthorizeResponse, OCPPBootNotificationResponse, OCPPDataTransferRequest, OCPPDataTransferResponse, OCPPFirmwareStatus, OCPPFirmwareStatusNotificationResponse, OCPPHeartbeatResponse, OCPPLocation, OCPPMeasurand, OCPPMeterValue, OCPPMeterValuesRequest, OCPPMeterValuesResponse, OCPPReadingContext, OCPPStartTransactionResponse, OCPPStatusNotificationRequest, OCPPStatusNotificationResponse, OCPPStopTransactionResponse, OCPPUnitOfMeasure, OCPPValueFormat, OCPPVersion } from '../../../src/types/ocpp/OCPPServer';
+import { AxiosResponse } from 'axios';
import CentralServerService from '../client/CentralServerService';
import ChargingStation from '../../types/ChargingStation';
import Constants from '../../../src/utils/Constants';
import ContextDefinition from './ContextDefinition';
import OCPPService from '../ocpp/OCPPService';
import TenantContext from './TenantContext';
+import Transaction from '../../types/Transaction';
import Utils from '../../../src/utils/Utils';
import faker from 'faker';
@@ -32,21 +34,21 @@ export default class ChargingStationContext {
private chargingStation: ChargingStation;
private ocppService: OCPPService;
private tenantContext: TenantContext;
- private transactionsStarted: OCPPStartTransactionResponse[] = [];
- private transactionsStopped: OCPPStopTransactionResponse[] = [];
+ private transactionsStarted: Map<number, OCPPStartTransactionResponse> = new Map();
+ private transactionsStopped: Map<number, OCPPStopTransactionResponse> = new Map();
- constructor(chargingStation, tenantContext) {
+ constructor(chargingStation: ChargingStation, tenantContext: TenantContext) {
this.chargingStation = chargingStation;
this.tenantContext = tenantContext;
}
- async initialize(token: string = null) {
+ public async initialize(token: string = null): Promise<void> {
this.ocppService = await this.tenantContext.getOCPPService(this.chargingStation.ocppVersion, token);
}
- async cleanUpCreatedData() {
+ public async cleanUpCreatedData(): Promise<void> {
// Clean up transactions
- for (const transaction of this.transactionsStarted) {
+ for (const transaction of this.transactionsStarted.values()) {
if (transaction.transactionId) {
const transactionResponse = await this.tenantContext.getAdminCentralServerService().transactionApi.readById(transaction.transactionId);
if (transactionResponse.status === 200) {
@@ -54,51 +56,44 @@ export default class ChargingStationContext {
}
}
}
+ this.transactionsStarted.clear();
}
- getChargingStation() {
+ public getChargingStation(): ChargingStation {
return this.chargingStation;
}
- addTransactionStarted(transaction) {
- this.transactionsStarted.push(transaction);
- }
-
- addTransactionStopped(transaction) {
- this.transactionsStopped.push(transaction);
- }
-
- async authorize(tagId: string): Promise<OCPPAuthorizeResponse> {
+ public async authorize(tagId: string): Promise<OCPPAuthorizeResponse> {
return this.ocppService.executeAuthorize(this.chargingStation.id, {
idTag: tagId
});
}
- async readChargingStation(userService?: CentralServerService) {
+ public async readChargingStation(userService?: CentralServerService): Promise<AxiosResponse<ChargingStation>> {
if (!userService) {
userService = new CentralServerService(this.tenantContext.getTenant().subdomain, this.tenantContext.getUserContext(ContextDefinition.USER_CONTEXTS.DEFAULT_ADMIN));
}
return await userService.chargingStationApi.readById(this.chargingStation.id);
}
- async sendHeartbeat(): Promise<OCPPHeartbeatResponse> {
+ public async sendHeartbeat(): Promise<OCPPHeartbeatResponse> {
return await this.ocppService.executeHeartbeat(this.chargingStation.id, {});
}
- async startTransaction(connectorId: number, tagId: string, meterStart: number, startDate: Date): Promise<OCPPStartTransactionResponse> {
+ public async startTransaction(connectorId: number, tagId: string, meterStart: number, startDate: Date): Promise<OCPPStartTransactionResponse> {
const response = await this.ocppService.executeStartTransaction(this.chargingStation.id, {
connectorId: connectorId,
idTag: tagId,
meterStart: meterStart,
timestamp: startDate.toISOString()
});
- if (response) {
+ if (response && response.transactionId > 0) {
this.addTransactionStarted(response);
}
return response;
}
- async stopTransaction(transactionId: number, tagId: string, meterStop: number, stopDate: Date, transactionData?: OCPPMeterValue[] | OCPP15TransactionData): Promise<OCPPStopTransactionResponse> {
+ public async stopTransaction(transactionId: number, tagId: string, meterStop: number, stopDate: Date, transactionData?: OCPPMeterValue[] | OCPP15TransactionData): Promise<OCPPStopTransactionResponse> {
// Check props
const response = await this.ocppService.executeStopTransaction(this.chargingStation.id, {
transactionId: transactionId,
@@ -107,23 +102,14 @@ export default class ChargingStationContext {
timestamp: stopDate.toISOString(),
transactionData: transactionData
});
- if (response) {
- this.addTransactionStopped(response);
- }
return response;
}
- public removeTransaction(transactionId: number) {
- for (let i = 0; i < this.transactionsStarted.length; i++) {
- const transaction = this.transactionsStarted[i];
- if (transaction.transactionId === transactionId) {
- this.transactionsStarted.splice(i, 1);
- break;
- }
- }
+ public removeTransaction(transactionId: number): void {
+ this.transactionsStarted.delete(transactionId);
}
- async sendConsumptionMeterValue(connectorId: number, transactionId: number, timestamp: Date, meterValues: MeterValueParams): Promise<OCPPMeterValuesResponse> {
+ public async sendConsumptionMeterValue(connectorId: number, transactionId: number, timestamp: Date, meterValues: MeterValueParams): Promise<OCPPMeterValuesResponse> {
let meterValueRequest: OCPPMeterValuesRequest | OCPP15MeterValuesRequest;
// OCPP 1.6?
if (this.chargingStation.ocppVersion === OCPPVersion.VERSION_16) {
@@ -251,17 +237,19 @@ export default class ChargingStationContext {
return this.ocppService.executeMeterValues(this.chargingStation.id, meterValueRequest);
}
- async sendBeginMeterValue(connectorId: number, transactionId: number, timestamp: Date, meterValues: MeterValueParams) {
+ public async sendBeginMeterValue(connectorId: number, transactionId: number,
+ timestamp: Date, meterValues: MeterValueParams): Promise<OCPPMeterValuesResponse> {
return this.sendBeginEndMeterValue(
OCPPReadingContext.TRANSACTION_BEGIN, connectorId, transactionId, timestamp, meterValues);
}
- async sendEndMeterValue(connectorId: number, transactionId: number, timestamp: Date, meterValues: MeterValueParams) {
+ public async sendEndMeterValue(connectorId: number, transactionId: number,
+ timestamp: Date, meterValues: MeterValueParams): Promise<OCPPMeterValuesResponse> {
return this.sendBeginEndMeterValue(
OCPPReadingContext.TRANSACTION_END, connectorId, transactionId, timestamp, meterValues);
}
- async sendBeginEndMeterValue(context: OCPPReadingContext.TRANSACTION_BEGIN | OCPPReadingContext.TRANSACTION_END,
+ public async sendBeginEndMeterValue(context: OCPPReadingContext.TRANSACTION_BEGIN | OCPPReadingContext.TRANSACTION_END,
connectorId: number, transactionId: number, timestamp: Date, meterValues: MeterValueParams): Promise<OCPPMeterValuesResponse> {
let meterValueRequest: OCPPMeterValuesRequest | OCPP15MeterValuesRequest;
// OCPP 1.6?
@@ -397,7 +385,7 @@ export default class ChargingStationContext {
return this.ocppService.executeMeterValues(this.chargingStation.id, meterValueRequest);
}
- async sendClockMeterValue(connectorId: number, transactionId: number, timestamp: Date, energyActiveImportMeterValue: number): Promise<OCPPMeterValuesResponse> {
+ public async sendClockMeterValue(connectorId: number, transactionId: number, timestamp: Date, energyActiveImportMeterValue: number): Promise<OCPPMeterValuesResponse> {
let response: OCPPMeterValuesResponse;
// OCPP 1.6?
if (this.chargingStation.ocppVersion === OCPPVersion.VERSION_16) {
@@ -433,7 +421,7 @@ export default class ChargingStationContext {
return response;
}
- async setConnectorStatus(connector: OCPPStatusNotificationRequest): Promise<OCPPStatusNotificationResponse> {
+ public async setConnectorStatus(connector: OCPPStatusNotificationRequest): Promise<OCPPStatusNotificationResponse> {
if (!Utils.objectHasProperty(connector, 'connectorId')) {
connector.connectorId = 1;
}
@@ -452,11 +440,11 @@ export default class ChargingStationContext {
return response;
}
- async transferData(data): Promise<OCPPDataTransferResponse> {
+ public async transferData(data: OCPPDataTransferRequest): Promise<OCPPDataTransferResponse> {
return this.ocppService.executeDataTransfer(this.chargingStation.id, data);
}
- async sendBootNotification(): Promise<OCPPBootNotificationResponse> {
+ public async sendBootNotification(): Promise<OCPPBootNotificationResponse> {
return this.ocppService.executeBootNotification(
this.chargingStation.id, {
chargeBoxSerialNumber: this.chargingStation.chargeBoxSerialNumber,
@@ -468,13 +456,13 @@ export default class ChargingStationContext {
);
}
- async sendFirmwareStatusNotification(status: OCPPFirmwareStatus): Promise<OCPPFirmwareStatusNotificationResponse> {
+ public async sendFirmwareStatusNotification(status: OCPPFirmwareStatus): Promise<OCPPFirmwareStatusNotificationResponse> {
return this.ocppService.executeFirmwareStatusNotification(
this.chargingStation.id, { status: status }
);
}
- getConfiguration() {
+ private getConfiguration() {
const configuration: any = {
'stationTemplate': {
'baseName': 'CS-' + faker.random.alphaNumeric(10),
@@ -514,4 +502,8 @@ export default class ChargingStationContext {
});
return configuration;
}
+
+ private addTransactionStarted(ocppStartTransactionResponse: OCPPStartTransactionResponse): void {
+ this.transactionsStarted.set(ocppStartTransactionResponse.transactionId, ocppStartTransactionResponse);
+ }
}

Fixed/Typed Unit Tests + Add logs in offline charger task