}
},
"eslint-plugin-jsdoc": {
- "version": "35.1.0",
- "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-35.1.0.tgz",
- "integrity": "sha512-XfLaI9kzXW1mihqmeTWH+fn5Zw+sbX48Jcmwp9dftwqegj6yT/3FNnuIxmM5VyLX3AdoBNDc8p4fje7/ZxVQyg==",
+ "version": "35.1.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-35.1.1.tgz",
+ "integrity": "sha512-pmhv0uNluRfFNAcy1rMI5Y0uw5i7EMo8dm7BV7hBUzHdHFlHdH/ZDGhmPh11QVvAEX9Gc0pCNjon4oUw5v0ovg==",
"dev": true,
"requires": {
"@es-joy/jsdoccomment": "^0.8.0-alpha.2",
"comment-parser": "1.1.5",
"debug": "^4.3.1",
"esquery": "^1.4.0",
- "jsdoc-type-pratt-parser": "^1.0.0",
+ "jsdoc-type-pratt-parser": "^1.0.1",
"lodash": "^4.17.21",
"regextras": "^0.8.0",
"semver": "^7.3.5",
"dev": true
},
"jsdoc-type-pratt-parser": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-1.0.0.tgz",
- "integrity": "sha512-aFubex6uQ7gdoU173Sqdw9Abm6EOCYDhXWhP7YlS201Z+e5Ik38AiDHlKMqoqd/WiiU3/aWz/NHV5X8GQipOTQ==",
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-1.0.1.tgz",
+ "integrity": "sha512-+bq+6jEywRhrF06tCvjV0ew0XdFsaWTcmfpLE+42KbU6imm0TwoJrWclDVoo/8iGf0bO4SibYJLsduMWRD18kA==",
"dev": true
},
"jsesc": {
"cross-env": "^7.0.3",
"eslint": "^7.27.0",
"eslint-plugin-import": "^2.23.4",
- "eslint-plugin-jsdoc": "^35.1.0",
+ "eslint-plugin-jsdoc": "^35.1.1",
"expect": "^27.0.2",
"mbt": "^1.2.1",
"mocha": "^8.4.0",
import ChargingStationInfo from '../types/ChargingStationInfo';
import Configuration from '../utils/Configuration';
import Constants from '../utils/Constants';
+import FileUtils from '../utils/FileUtils';
import { MessageType } from '../types/ocpp/MessageType';
import { MeterValueMeasurand } from '../types/ocpp/MeterValues';
import OCPP16IncomingRequestService from './ocpp/1.6/OCCP16IncomingRequestService';
stationTemplateFromFile = JSON.parse(fs.readFileSync(fileDescriptor, 'utf8')) as ChargingStationTemplate;
fs.closeSync(fileDescriptor);
} catch (error) {
- logger.error('Template file ' + this.stationTemplateFile + ' loading error: %j', error);
- throw error;
+ FileUtils.handleFileException(this.logPrefix(), 'Template', this.stationTemplateFile, error);
}
const stationInfo: ChargingStationInfo = stationTemplateFromFile || {} as ChargingStationInfo;
if (!Utils.isEmptyArray(stationTemplateFromFile.power)) {
authorizedTags = JSON.parse(fs.readFileSync(fileDescriptor, 'utf8')) as string[];
fs.closeSync(fileDescriptor);
} catch (error) {
- logger.error(this.logPrefix() + ' Authorization file ' + authorizationFile + ' loading error: %j', error);
- throw error;
+ FileUtils.handleFileException(this.logPrefix(), 'Authorization', authorizationFile, error);
}
} else {
logger.info(this.logPrefix() + ' No authorization file given in template file ' + this.stationTemplateFile);
}
private startAuthorizationFileMonitoring(): void {
- fs.watch(this.getAuthorizationFile()).on('change', (e) => {
+ const authorizationFile = this.getAuthorizationFile();
+ if (authorizationFile) {
try {
- logger.debug(this.logPrefix() + ' Authorization file ' + this.getAuthorizationFile() + ' have changed, reload');
- // Initialize authorizedTags
- this.authorizedTags = this.getAuthorizedTags();
+ fs.watch(authorizationFile).on('change', (e) => {
+ try {
+ logger.debug(this.logPrefix() + ' Authorization file ' + authorizationFile + ' have changed, reload');
+ // Initialize authorizedTags
+ this.authorizedTags = this.getAuthorizedTags();
+ } catch (error) {
+ logger.error(this.logPrefix() + ' Authorization file monitoring error: %j', error);
+ }
+ });
} catch (error) {
- logger.error(this.logPrefix() + ' Authorization file monitoring error: %j', error);
+ FileUtils.handleFileException(this.logPrefix(), 'Authorization', authorizationFile, error);
}
- });
+ } else {
+ logger.info(this.logPrefix() + ' No authorization file given in template file ' + this.stationTemplateFile + '. Not monitoring changes');
+ }
}
private startStationTemplateFileMonitoring(): void {
+ try {
// eslint-disable-next-line @typescript-eslint/no-misused-promises
- fs.watch(this.stationTemplateFile).on('change', async (e): Promise<void> => {
- try {
- logger.debug(this.logPrefix() + ' Template file ' + this.stationTemplateFile + ' have changed, reload');
- // Initialize
- this.initialize();
- // Stop the ATG
- if (!this.stationInfo.AutomaticTransactionGenerator.enable &&
+ fs.watch(this.stationTemplateFile).on('change', async (e): Promise<void> => {
+ 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) {
- await this.automaticTransactionGeneration.stop();
+ await this.automaticTransactionGeneration.stop();
+ }
+ // Start the ATG
+ this.startAutomaticTransactionGenerator();
+ // 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);
}
- // Start the ATG
- this.startAutomaticTransactionGenerator();
- // 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);
- }
- });
+ });
+ } catch (error) {
+ FileUtils.handleFileException(this.logPrefix(), 'Template', this.stationTemplateFile, error);
+ }
}
private getReconnectExponentialDelay(): boolean | undefined {
static getStationTemplateURLs(): StationTemplateURL[] {
Configuration.getConfig().stationTemplateURLs.forEach((stationURL: StationTemplateURL) => {
if (!Configuration.isUndefined(stationURL['numberOfStation'])) {
- console.error(`Deprecated configuration key 'numberOfStation' usage for template file '${stationURL.file}' in 'stationTemplateURLs'. Use 'numberOfStations' instead`);
+ console.error(`${Configuration.logPrefix()} Deprecated configuration key 'numberOfStation' usage for template file '${stationURL.file}' in 'stationTemplateURLs'. Use 'numberOfStations' instead`);
}
});
// Read conf
return Configuration.objectHasOwnProperty(Configuration.getConfig(), 'distributeStationsToTenantsEqually') ? Configuration.getConfig().distributeStationsToTenantsEqually : true;
}
+ private static logPrefix(): string {
+ return new Date().toLocaleString() + ' Simulator configuration |';
+ }
+
private static deprecateConfigurationKey(key: string, logMsgToAppend = '') {
if (!Configuration.isUndefined(Configuration.getConfig()[key])) {
- console.error(`Deprecated configuration key '${key}' usage${logMsgToAppend && '. ' + logMsgToAppend}`);
+ console.error(`${Configuration.logPrefix()} Deprecated configuration key '${key}' usage${logMsgToAppend && '. ' + logMsgToAppend}`);
}
}
// Read the config file
private static getConfig(): ConfigurationData {
if (!Configuration.configuration) {
- Configuration.configuration = JSON.parse(fs.readFileSync(Configuration.configurationFilePath, 'utf8')) as ConfigurationData;
+ try {
+ Configuration.configuration = JSON.parse(fs.readFileSync(Configuration.configurationFilePath, 'utf8')) as ConfigurationData;
+ } catch (error) {
+ Configuration.handleFileException(Configuration.logPrefix(), 'Configuration', Configuration.configurationFilePath, error);
+ }
if (!Configuration.configurationFileWatcher) {
Configuration.configurationFileWatcher = Configuration.getConfigurationFileWatcher();
}
}
private static getConfigurationFileWatcher(): fs.FSWatcher {
+ try {
// eslint-disable-next-line @typescript-eslint/no-misused-promises
- return fs.watch(Configuration.configurationFilePath).on('change', async (e): Promise<void> => {
- // Nullify to force configuration file reading
- Configuration.configuration = null;
- if (!Configuration.isUndefined(Configuration.configurationChangeCallback)) {
- await Configuration.configurationChangeCallback();
- }
- });
+ return fs.watch(Configuration.configurationFilePath).on('change', async (e): Promise<void> => {
+ // Nullify to force configuration file reading
+ Configuration.configuration = null;
+ if (!Configuration.isUndefined(Configuration.configurationChangeCallback)) {
+ await Configuration.configurationChangeCallback();
+ }
+ });
+ } catch (error) {
+ Configuration.handleFileException(Configuration.logPrefix(), 'Configuration', Configuration.configurationFilePath, error);
+ }
}
private static objectHasOwnProperty(object: any, property: string): boolean {
- return Object.prototype.hasOwnProperty.call(object, property);
+ return Object.prototype.hasOwnProperty.call(object, property) as boolean;
}
private static isUndefined(obj: any): boolean {
return typeof obj === 'undefined';
}
+
+ private static handleFileException(logPrefix: string, fileType: string, filePath: string, error: NodeJS.ErrnoException): void {
+ const prefix = logPrefix.length !== 0 ? logPrefix + ' ' : '';
+ if (error.code === 'ENOENT') {
+ console.error(prefix + fileType + ' file ' + filePath + ' not found: ', error);
+ } else {
+ console.error(prefix + fileType + ' file ' + filePath + ' opening error: ', error);
+ }
+ throw error;
+ }
}
--- /dev/null
+import logger from './Logger';
+
+export default class FileUtils {
+ static handleFileException(logPrefix: string, fileType: string, filePath: string, error: NodeJS.ErrnoException, consoleOut = false): void {
+ const prefix = logPrefix.length !== 0 ? logPrefix + ' ' : '';
+ if (error.code === 'ENOENT') {
+ if (consoleOut) {
+ console.error(prefix + fileType + ' file ' + filePath + ' not found: ', error);
+ } else {
+ logger.error(prefix + fileType + ' file ' + filePath + ' not found: %j', error);
+ }
+ } else {
+ if (consoleOut) {
+ console.error(prefix + fileType + ' file ' + filePath + ' opening error: ', error);
+ } else {
+ logger.error(prefix + fileType + ' file ' + filePath + ' opening error: %j', error);
+ }
+ throw error;
+ }
+ }
+}
}
static logPrefix(prefixString = ''): string {
- const date = new Date();
- return date.toLocaleString() + prefixString;
+ return new Date().toLocaleString() + prefixString;
}
static cloneObject<T>(object: T): T {