dist/
+ui/web
# FIXME: ESM import parse error
build-requirements.js
--- /dev/null
+// eslint-disable-next-line n/no-unpublished-require
+const { defineConfig } = require('eslint-define-config')
+
+module.exports = defineConfig({
+ root: true,
+ env: {
+ es2022: true,
+ node: true
+ },
+ parserOptions: {
+ ecmaVersion: 2022,
+ sourceType: 'module'
+ },
+ plugins: ['import'],
+ extends: ['eslint:recommended', 'plugin:import/recommended'],
+ settings: {
+ 'import/resolver': {
+ typescript: {
+ project: './tsconfig.json'
+ }
+ }
+ },
+ rules: {
+ 'sort-imports': [
+ 'error',
+ {
+ ignoreCase: false,
+ ignoreDeclarationSort: true,
+ ignoreMemberSort: false,
+ memberSyntaxSortOrder: ['none', 'all', 'multiple', 'single'],
+ allowSeparatedGroups: true
+ }
+ ],
+ 'import/order': [
+ 'error',
+ {
+ groups: [
+ 'builtin', // Built-in imports (come from NodeJS native) go first
+ 'external', // <- External imports
+ 'internal', // <- Absolute imports
+ ['sibling', 'parent'], // <- Relative imports, the sibling and parent types they can be mingled together
+ 'index', // <- Index imports
+ 'unknown' // <- Unknown
+ ],
+ 'newlines-between': 'always',
+ alphabetize: {
+ /* Sort in ascending order. Options: ["ignore", "asc", "desc"] */
+ order: 'asc',
+ /* Ignore case. Options: [true, false] */
+ caseInsensitive: true
+ }
+ }
+ ]
+ },
+ overrides: [
+ {
+ files: ['**/*.ts'],
+ parser: '@typescript-eslint/parser',
+ parserOptions: {
+ project: './tsconfig.json'
+ },
+ plugins: ['@typescript-eslint', 'eslint-plugin-tsdoc'],
+ extends: [
+ 'plugin:@typescript-eslint/recommended-type-checked',
+ 'plugin:@typescript-eslint/stylistic-type-checked',
+ 'plugin:import/typescript',
+ 'standard-with-typescript'
+ ],
+ rules: {
+ 'operator-linebreak': 'off',
+ 'tsdoc/syntax': 'warn'
+ }
+ },
+ {
+ files: ['**/*.js', '**/*.cjs', '**/*.mjs'],
+ plugins: ['jsdoc'],
+ extends: ['plugin:n/recommended', 'plugin:jsdoc/recommended', 'standard'],
+ rules: {
+ 'n/shebang': 'off'
+ }
+ }
+ ]
+})
+++ /dev/null
-{
- "$schema": "https://json.schemastore.org/eslintrc",
- "root": true,
- "env": {
- "es2022": true,
- "node": true
- },
- "parserOptions": {
- "ecmaVersion": 2022,
- "sourceType": "module"
- },
- "plugins": ["import"],
- "extends": ["eslint:recommended", "plugin:import/recommended", "plugin:prettier/recommended"],
- "settings": {
- "import/resolver": {
- "typescript": {
- "project": "./tsconfig.json"
- }
- }
- },
- "rules": {
- "semi": ["error", "always"],
- "space-before-blocks": ["error", "always"],
- "curly": ["error", "all"],
- "brace-style": "error",
- "no-else-return": "error",
- "no-extra-bind": "error",
- "no-lone-blocks": "error",
- "no-multi-spaces": "error",
- "no-empty": "error",
- "no-return-assign": ["error", "always"],
- "no-useless-catch": "error",
- "no-useless-return": "error",
- "no-multiple-empty-lines": [
- "error",
- {
- "max": 2,
- "maxEOF": 1
- }
- ],
- "block-spacing": "error",
- "eol-last": ["error", "always"],
- "consistent-this": ["error", "self"],
- "func-call-spacing": ["error", "never"],
- "keyword-spacing": ["error"],
- "id-blacklist": [
- "error",
- "any",
- "Number",
- "number",
- "String",
- "string",
- "Boolean",
- "boolean",
- "Undefined",
- "undefined",
- "Symbol",
- "symbol"
- ],
- "linebreak-style": ["error", "unix"],
- "max-len": [
- "warn",
- {
- "code": 100,
- "ignoreUrls": true
- }
- ],
- "no-lonely-if": "error",
- "no-trailing-spaces": "error",
- "no-whitespace-before-property": "error",
- "no-shadow": "error",
- "space-in-parens": ["error", "never"],
- "space-infix-ops": "error",
- "space-unary-ops": "error",
- "spaced-comment": ["error", "always"],
- "switch-colon-spacing": "error",
- "arrow-parens": ["error", "always"],
- "arrow-spacing": "error",
- "no-duplicate-imports": "error",
- "no-var": "error",
- "prefer-const": "error",
- "sort-imports": [
- "error",
- {
- "ignoreCase": false,
- "ignoreDeclarationSort": true,
- "ignoreMemberSort": false,
- "memberSyntaxSortOrder": ["none", "all", "multiple", "single"],
- "allowSeparatedGroups": true
- }
- ],
- "import/order": [
- "error",
- {
- "groups": [
- "builtin", // Built-in imports (come from NodeJS native) go first
- "external", // <- External imports
- "internal", // <- Absolute imports
- ["sibling", "parent"], // <- Relative imports, the sibling and parent types they can be mingled together
- "index", // <- Index imports
- "unknown" // <- Unknown
- ],
- "newlines-between": "always",
- "alphabetize": {
- /* Sort in ascending order. Options: ["ignore", "asc", "desc"] */
- "order": "asc",
- /* Ignore case. Options: [true, false] */
- "caseInsensitive": true
- }
- }
- ],
- "object-curly-spacing": ["error", "always"],
- "lines-between-class-members": [
- "error",
- "always",
- {
- "exceptAfterSingleLine": true
- }
- ],
- "quotes": [
- "error",
- "single",
- {
- "avoidEscape": true,
- "allowTemplateLiterals": false
- }
- ]
- },
- "overrides": [
- {
- "files": ["**/*.ts"],
- "parser": "@typescript-eslint/parser",
- "parserOptions": {
- "project": true,
- "tsconfigRootDir": "./"
- },
- "plugins": ["@typescript-eslint", "eslint-plugin-tsdoc"],
- "extends": [
- "plugin:@typescript-eslint/recommended-type-checked",
- "plugin:@typescript-eslint/stylistic-type-checked",
- "plugin:import/typescript"
- ],
- "rules": {
- "tsdoc/syntax": "warn",
- "@typescript-eslint/array-type": "off",
- "semi": "off",
- "@typescript-eslint/semi": ["error", "always"],
- "@typescript-eslint/no-empty-function": "warn",
- "@typescript-eslint/member-ordering": "error",
- "@typescript-eslint/await-thenable": "error",
- "@typescript-eslint/no-floating-promises": "error",
- "@typescript-eslint/promise-function-async": "error",
- "@typescript-eslint/no-misused-promises": "error",
- "no-shadow": "off",
- "@typescript-eslint/no-shadow": "error"
- }
- },
- {
- "files": ["**/*.js", "**/*.cjs", "**/*.mjs"],
- "plugins": ["jsdoc"],
- "extends": ["plugin:jsdoc/recommended", "plugin:n/recommended"],
- "rules": {
- "n/shebang": "off"
- }
- }
- ]
-}
export default {
'{src,tests}/**/*.{ts,tsx,cts,mts}': ['prettier --cache --write', 'eslint --cache --fix'],
'**/*.{json,md,yml,yaml}': ['prettier --cache --write'],
- '**/*.{js,jsx,cjs,mjs}': ['prettier --cache --write', 'eslint --cache --fix'],
-};
+ '**/*.{js,jsx,cjs,mjs}': ['prettier --cache --write', 'eslint --cache --fix']
+}
{
"$schema": "https://json.schemastore.org/prettierrc",
"printWidth": 100,
- "singleQuote": true
+ "semi": false,
+ "singleQuote": true,
+ "trailingComma": "none"
}
```ts
type AutomaticTransactionGeneratorConfiguration = {
- enable: boolean;
- minDuration: number;
- maxDuration: number;
- minDelayBetweenTwoTransactions: number;
- maxDelayBetweenTwoTransactions: number;
- probabilityOfStart: number;
- stopAfterHours: number;
- stopOnConnectionFailure: boolean;
- requireAuthorize?: boolean;
- idTagDistribution?: 'random' | 'round-robin' | 'connector-affinity';
-};
+ enable: boolean
+ minDuration: number
+ maxDuration: number
+ minDelayBetweenTwoTransactions: number
+ maxDelayBetweenTwoTransactions: number
+ probabilityOfStart: number
+ stopAfterHours: number
+ stopOnConnectionFailure: boolean
+ requireAuthorize?: boolean
+ idTagDistribution?: 'random' | 'round-robin' | 'connector-affinity'
+}
```
##### Example:
-import chalk from 'chalk';
-import semVer from 'semver';
-import packageJson from './package.json' assert { type: 'json' };
-import { version, exit } from 'node:process';
+import chalk from 'chalk'
+import semVer from 'semver'
+import packageJson from './package.json' assert { type: 'json' }
+import { version, exit } from 'node:process'
/**
* Check if the current node version match the required engines version.
*/
export const checkNodeVersion = () => {
- const enginesNodeVersion = packageJson.engines.node;
+ const enginesNodeVersion = packageJson.engines.node
if (semVer.satisfies(version, enginesNodeVersion) === false) {
console.error(
chalk.red(
- `Required node version ${enginesNodeVersion} not satisfied with current version ${version}.`,
- ),
- );
+ `Required node version ${enginesNodeVersion} not satisfied with current version ${version}.`
+ )
+ )
// eslint-disable-next-line n/no-process-exit
- exit(1);
+ exit(1)
}
-};
+}
-checkNodeVersion();
+checkNodeVersion()
/* eslint-disable n/no-unpublished-import */
-import { env } from 'node:process';
+import { env } from 'node:process'
-import chalk from 'chalk';
-import { build } from 'esbuild';
-import { clean } from 'esbuild-plugin-clean';
-import { copy } from 'esbuild-plugin-copy';
+import chalk from 'chalk'
+import { build } from 'esbuild'
+import { clean } from 'esbuild-plugin-clean'
+import { copy } from 'esbuild-plugin-copy'
-const isDevelopmentBuild = env.BUILD === 'development';
-const sourcemap = !!isDevelopmentBuild;
+const isDevelopmentBuild = env.BUILD === 'development'
+const sourcemap = !!isDevelopmentBuild
-(async () => {
- console.info(
- chalk.green(`Building in ${isDevelopmentBuild ? 'development' : 'production'} mode`),
- );
- console.time('Build time');
+;(async () => {
+ console.info(chalk.green(`Building in ${isDevelopmentBuild ? 'development' : 'production'} mode`))
+ console.time('Build time')
await build({
entryPoints: ['./src/start.ts', './src/charging-station/ChargingStationWorker.ts'],
bundle: true,
'winston',
'winston/*',
'winston-daily-rotate-file',
- 'ws',
+ 'ws'
],
minify: true,
sourcemap,
'./dist/assets/*.json',
'./dist/assets/json-schemas',
'./dist/assets/station-templates',
- './dist/assets/ui-protocol',
- ],
+ './dist/assets/ui-protocol'
+ ]
}),
copy({
assets: [
{
from: ['./src/assets/config.json'],
- to: ['./assets'],
+ to: ['./assets']
},
{
from: ['./src/assets/idtags!(-template)*.json'],
- to: ['./assets'],
+ to: ['./assets']
},
{
from: ['./src/assets/json-schemas/**/*.json'],
- to: ['./assets/json-schemas'],
+ to: ['./assets/json-schemas']
},
{
from: ['./src/assets/station-templates/**/*.json'],
- to: ['./assets/station-templates'],
- },
- ],
- }),
- ],
- });
- console.timeEnd('Build time');
-})();
+ to: ['./assets/station-templates']
+ }
+ ]
+ })
+ ]
+ })
+ console.timeEnd('Build time')
+})()
-export default { extends: ['@commitlint/config-conventional'] };
+export default { extends: ['@commitlint/config-conventional'] }
-import { dirname, join } from 'node:path';
-import { fileURLToPath } from 'node:url';
+import { dirname, join } from 'node:path'
+import { fileURLToPath } from 'node:url'
-import { TsMorphMetadataProvider } from '@mikro-orm/reflection';
+import { TsMorphMetadataProvider } from '@mikro-orm/reflection'
-import { PerformanceData, PerformanceRecord } from './src/types';
-import { Constants } from './src/utils';
+import { PerformanceData, PerformanceRecord } from './src/types/index.js'
+import { Constants } from './src/utils/index.js'
export default {
metadataProvider: TsMorphMetadataProvider,
type: 'sqlite',
clientUrl: `file://${join(
dirname(fileURLToPath(import.meta.url)),
- `${Constants.DEFAULT_PERFORMANCE_RECORDS_DB_NAME}.db`,
- )}`,
-};
+ `${Constants.DEFAULT_PERFORMANCE_RECORDS_DB_NAME}.db`
+ )}`
+}
"clean:node_modules": "npx rimraf node_modules",
"lint": "cross-env TIMING=1 eslint --cache src",
"lint:fix": "cross-env TIMING=1 eslint --cache --fix src",
- "format": "prettier --cache --write .",
+ "format": "prettier --cache --write .; ts-standard --fix .",
"test": "glob -c \"c8 node --import tsx --test\" \"tests/**/*.test.ts\"",
"test:debug": "glob -c \"node --import tsx --test --inspect\" \"tests/**/*.test.ts\"",
"coverage": "c8 report --reporter=lcov",
"esbuild-plugin-copy": "^2.1.1",
"eslint": "^8.56.0",
"eslint-config-prettier": "^9.1.0",
+ "eslint-config-standard": "^17.1.0",
+ "eslint-config-standard-with-typescript": "^43.0.0",
+ "eslint-define-config": "^2.1.0",
"eslint-import-resolver-typescript": "^3.6.1",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-jsdoc": "^46.9.1",
"release-it": "^17.0.1",
"rimraf": "^5.0.5",
"semver": "^7.5.4",
+ "ts-node": "^10.9.2",
+ "ts-standard": "^12.0.2",
"tsx": "^4.7.0",
"typescript": "~5.3.3"
}
eslint-config-prettier:
specifier: ^9.1.0
version: 9.1.0(eslint@8.56.0)
+ eslint-config-standard:
+ specifier: ^17.1.0
+ version: 17.1.0(eslint-plugin-import@2.29.1)(eslint-plugin-n@16.5.0)(eslint-plugin-promise@6.1.1)(eslint@8.56.0)
+ eslint-config-standard-with-typescript:
+ specifier: ^43.0.0
+ version: 43.0.0(@typescript-eslint/eslint-plugin@6.16.0)(eslint-plugin-import@2.29.1)(eslint-plugin-n@16.5.0)(eslint-plugin-promise@6.1.1)(eslint@8.56.0)(typescript@5.3.3)
+ eslint-define-config:
+ specifier: ^2.1.0
+ version: 2.1.0
eslint-import-resolver-typescript:
specifier: ^3.6.1
version: 3.6.1(@typescript-eslint/parser@6.16.0)(eslint-plugin-import@2.29.1)(eslint@8.56.0)
semver:
specifier: ^7.5.3
version: 7.5.4
+ ts-node:
+ specifier: ^10.9.2
+ version: 10.9.2(@types/node@20.10.5)(typescript@5.3.3)
+ ts-standard:
+ specifier: ^12.0.2
+ version: 12.0.2(eslint-import-resolver-typescript@3.6.1)(typescript@5.3.3)
tsx:
specifier: ^4.7.0
version: 4.7.0
chalk: 4.1.2
dev: true
+ /@cspotcode/source-map-support@0.8.1:
+ resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==}
+ engines: {node: '>=12'}
+ dependencies:
+ '@jridgewell/trace-mapping': 0.3.9
+ dev: true
+
/@dabh/diagnostics@2.0.3:
resolution: {integrity: sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==}
dependencies:
'@jridgewell/sourcemap-codec': 1.4.15
dev: true
+ /@jridgewell/trace-mapping@0.3.9:
+ resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==}
+ dependencies:
+ '@jridgewell/resolve-uri': 3.1.1
+ '@jridgewell/sourcemap-codec': 1.4.15
+ dev: true
+
/@ljharb/through@2.3.11:
resolution: {integrity: sha512-ccfcIDlogiXNq5KcbAwbaO7lMh3Tm1i3khMPYpxlK8hH/W53zN81KM9coerRLOnTGu3nfXIniAmQbRI9OxbC0w==}
engines: {node: '>= 0.4'}
path-browserify: 1.0.1
dev: false
+ /@tsconfig/node10@1.0.9:
+ resolution: {integrity: sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==}
+ dev: true
+
+ /@tsconfig/node12@1.0.11:
+ resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==}
+ dev: true
+
+ /@tsconfig/node14@1.0.3:
+ resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==}
+ dev: true
+
+ /@tsconfig/node16@1.0.4:
+ resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==}
+ dev: true
+
/@types/geojson@7946.0.13:
resolution: {integrity: sha512-bmrNrgKMOhM3WsafmbGmC+6dsF2Z308vLFsQ3a/bT8X8Sv5clVYpPars/UPq+sAaJP+5OoLAYgwbkS5QEJdLUQ==}
'@types/yargs-parser': 21.0.3
dev: true
+ /@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.56.0)(typescript@5.3.3):
+ resolution: {integrity: sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ peerDependencies:
+ '@typescript-eslint/parser': ^5.0.0
+ eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
+ typescript: '*'
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+ dependencies:
+ '@eslint-community/regexpp': 4.10.0
+ '@typescript-eslint/parser': 5.62.0(eslint@8.56.0)(typescript@5.3.3)
+ '@typescript-eslint/scope-manager': 5.62.0
+ '@typescript-eslint/type-utils': 5.62.0(eslint@8.56.0)(typescript@5.3.3)
+ '@typescript-eslint/utils': 5.62.0(eslint@8.56.0)(typescript@5.3.3)
+ debug: 4.3.4
+ eslint: 8.56.0
+ graphemer: 1.4.0
+ ignore: 5.3.0
+ natural-compare-lite: 1.4.0
+ semver: 7.5.4
+ tsutils: 3.21.0(typescript@5.3.3)
+ typescript: 5.3.3
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
/@typescript-eslint/eslint-plugin@6.16.0(@typescript-eslint/parser@6.16.0)(eslint@8.56.0)(typescript@5.3.3):
resolution: {integrity: sha512-O5f7Kv5o4dLWQtPX4ywPPa+v9G+1q1x8mz0Kr0pXUtKsevo+gIJHLkGc8RxaZWtP8RrhwhSNIWThnW42K9/0rQ==}
engines: {node: ^16.0.0 || >=18.0.0}
- supports-color
dev: true
+ /@typescript-eslint/parser@5.62.0(eslint@8.56.0)(typescript@5.3.3):
+ resolution: {integrity: sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ peerDependencies:
+ eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
+ typescript: '*'
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+ dependencies:
+ '@typescript-eslint/scope-manager': 5.62.0
+ '@typescript-eslint/types': 5.62.0
+ '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.3.3)
+ debug: 4.3.4
+ eslint: 8.56.0
+ typescript: 5.3.3
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
/@typescript-eslint/parser@6.16.0(eslint@8.56.0)(typescript@5.3.3):
resolution: {integrity: sha512-H2GM3eUo12HpKZU9njig3DF5zJ58ja6ahj1GoHEHOgQvYxzoFJJEvC1MQ7T2l9Ha+69ZSOn7RTxOdpC/y3ikMw==}
engines: {node: ^16.0.0 || >=18.0.0}
- supports-color
dev: true
+ /@typescript-eslint/scope-manager@5.62.0:
+ resolution: {integrity: sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ dependencies:
+ '@typescript-eslint/types': 5.62.0
+ '@typescript-eslint/visitor-keys': 5.62.0
+ dev: true
+
/@typescript-eslint/scope-manager@6.16.0:
resolution: {integrity: sha512-0N7Y9DSPdaBQ3sqSCwlrm9zJwkpOuc6HYm7LpzLAPqBL7dmzAUimr4M29dMkOP/tEwvOCC/Cxo//yOfJD3HUiw==}
engines: {node: ^16.0.0 || >=18.0.0}
'@typescript-eslint/visitor-keys': 6.16.0
dev: true
+ /@typescript-eslint/type-utils@5.62.0(eslint@8.56.0)(typescript@5.3.3):
+ resolution: {integrity: sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ peerDependencies:
+ eslint: '*'
+ typescript: '*'
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+ dependencies:
+ '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.3.3)
+ '@typescript-eslint/utils': 5.62.0(eslint@8.56.0)(typescript@5.3.3)
+ debug: 4.3.4
+ eslint: 8.56.0
+ tsutils: 3.21.0(typescript@5.3.3)
+ typescript: 5.3.3
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
/@typescript-eslint/type-utils@6.16.0(eslint@8.56.0)(typescript@5.3.3):
resolution: {integrity: sha512-ThmrEOcARmOnoyQfYkHw/DX2SEYBalVECmoldVuH6qagKROp/jMnfXpAU/pAIWub9c4YTxga+XwgAkoA0pxfmg==}
engines: {node: ^16.0.0 || >=18.0.0}
- supports-color
dev: true
+ /@typescript-eslint/types@5.62.0:
+ resolution: {integrity: sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ dev: true
+
/@typescript-eslint/types@6.16.0:
resolution: {integrity: sha512-hvDFpLEvTJoHutVl87+MG/c5C8I6LOgEx05zExTSJDEVU7hhR3jhV8M5zuggbdFCw98+HhZWPHZeKS97kS3JoQ==}
engines: {node: ^16.0.0 || >=18.0.0}
dev: true
+ /@typescript-eslint/typescript-estree@5.62.0(typescript@5.3.3):
+ resolution: {integrity: sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ peerDependencies:
+ typescript: '*'
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+ dependencies:
+ '@typescript-eslint/types': 5.62.0
+ '@typescript-eslint/visitor-keys': 5.62.0
+ debug: 4.3.4
+ globby: 11.1.0
+ is-glob: 4.0.3
+ semver: 7.5.4
+ tsutils: 3.21.0(typescript@5.3.3)
+ typescript: 5.3.3
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
/@typescript-eslint/typescript-estree@6.16.0(typescript@5.3.3):
resolution: {integrity: sha512-VTWZuixh/vr7nih6CfrdpmFNLEnoVBF1skfjdyGnNwXOH1SLeHItGdZDHhhAIzd3ACazyY2Fg76zuzOVTaknGA==}
engines: {node: ^16.0.0 || >=18.0.0}
- supports-color
dev: true
+ /@typescript-eslint/utils@5.62.0(eslint@8.56.0)(typescript@5.3.3):
+ resolution: {integrity: sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ peerDependencies:
+ eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
+ dependencies:
+ '@eslint-community/eslint-utils': 4.4.0(eslint@8.56.0)
+ '@types/json-schema': 7.0.15
+ '@types/semver': 7.5.6
+ '@typescript-eslint/scope-manager': 5.62.0
+ '@typescript-eslint/types': 5.62.0
+ '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.3.3)
+ eslint: 8.56.0
+ eslint-scope: 5.1.1
+ semver: 7.5.4
+ transitivePeerDependencies:
+ - supports-color
+ - typescript
+ dev: true
+
/@typescript-eslint/utils@6.16.0(eslint@8.56.0)(typescript@5.3.3):
resolution: {integrity: sha512-T83QPKrBm6n//q9mv7oiSvy/Xq/7Hyw9SzSEhMHJwznEmQayfBM87+oAlkNAMEO7/MjIwKyOHgBJbxB0s7gx2A==}
engines: {node: ^16.0.0 || >=18.0.0}
- typescript
dev: true
+ /@typescript-eslint/visitor-keys@5.62.0:
+ resolution: {integrity: sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ dependencies:
+ '@typescript-eslint/types': 5.62.0
+ eslint-visitor-keys: 3.4.3
+ dev: true
+
/@typescript-eslint/visitor-keys@6.16.0:
resolution: {integrity: sha512-QSFQLruk7fhs91a/Ep/LqRdbJCZ1Rq03rqBdKT5Ky17Sz8zRLUksqIe9DW0pKtg/Z35/ztbLQ6qpOCN6rOC11A==}
engines: {node: ^16.0.0 || >=18.0.0}
readable-stream: 3.6.2
optional: true
+ /arg@4.1.3:
+ resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==}
+ dev: true
+
/argparse@2.0.1:
resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
dev: true
is-string: 1.0.7
dev: true
+ /array.prototype.tosorted@1.1.2:
+ resolution: {integrity: sha512-HuQCHOlk1Weat5jzStICBCd83NxiIMwqDg/dHEsoefabn/hJRj5pVdWcPUSpRrwhwxZOsQassMpgN/xRYFBMIg==}
+ dependencies:
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ es-abstract: 1.22.3
+ es-shim-unscopables: 1.0.2
+ get-intrinsic: 1.2.2
+ dev: true
+
/arraybuffer.prototype.slice@1.0.2:
resolution: {integrity: sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==}
engines: {node: '>= 0.4'}
/async@3.2.5:
resolution: {integrity: sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==}
+ /asynciterator.prototype@1.0.0:
+ resolution: {integrity: sha512-wwHYEIS0Q80f5mosx3L/dfG5t5rjEa9Ft51GTaNt862EnpyGHpgz2RkZvLPp1oF5TnAiTohkEKVEu8pQPJI7Vg==}
+ dependencies:
+ has-symbols: 1.0.3
+ dev: true
+
/asynckit@0.4.0:
resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
dev: true
sha.js: 2.4.11
dev: true
+ /create-require@1.1.1:
+ resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==}
+ dev: true
+
/cross-argv@1.0.0:
resolution: {integrity: sha512-uAVe/bgNHlPdP1VE4Sk08u9pAJ7o1x/tVQtX77T5zlhYhuwOWtVkPBEtHdvF5cq48VzeCG5i1zN4dQc8pwLYrw==}
dev: true
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dev: true
+ /diff@4.0.2:
+ resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==}
+ engines: {node: '>=0.3.1'}
+ dev: true
+
/diffie-hellman@5.0.3:
resolution: {integrity: sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==}
dependencies:
stop-iteration-iterator: 1.0.0
dev: true
+ /es-iterator-helpers@1.0.15:
+ resolution: {integrity: sha512-GhoY8uYqd6iwUl2kgjTm4CZAf6oo5mHK7BPqx3rKgx893YSsy0LGHV6gfqqQvZt/8xM8xeOnfXBCfqclMKkJ5g==}
+ dependencies:
+ asynciterator.prototype: 1.0.0
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ es-abstract: 1.22.3
+ es-set-tostringtag: 2.0.2
+ function-bind: 1.1.2
+ get-intrinsic: 1.2.2
+ globalthis: 1.0.3
+ has-property-descriptors: 1.0.1
+ has-proto: 1.0.1
+ has-symbols: 1.0.3
+ internal-slot: 1.0.6
+ iterator.prototype: 1.1.2
+ safe-array-concat: 1.0.1
+ dev: true
+
/es-set-tostringtag@2.0.2:
resolution: {integrity: sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==}
engines: {node: '>= 0.4'}
eslint: 8.56.0
dev: true
+ /eslint-config-standard-jsx@11.0.0(eslint-plugin-react@7.33.2)(eslint@8.56.0):
+ resolution: {integrity: sha512-+1EV/R0JxEK1L0NGolAr8Iktm3Rgotx3BKwgaX+eAuSX8D952LULKtjgZD3F+e6SvibONnhLwoTi9DPxN5LvvQ==}
+ peerDependencies:
+ eslint: ^8.8.0
+ eslint-plugin-react: ^7.28.0
+ dependencies:
+ eslint: 8.56.0
+ eslint-plugin-react: 7.33.2(eslint@8.56.0)
+ dev: true
+
+ /eslint-config-standard-with-typescript@23.0.0(@typescript-eslint/eslint-plugin@5.62.0)(eslint-plugin-import@2.29.1)(eslint-plugin-n@15.7.0)(eslint-plugin-promise@6.1.1)(eslint@8.56.0)(typescript@5.3.3):
+ resolution: {integrity: sha512-iaaWifImn37Z1OXbNW1es7KI+S7D408F9ys0bpaQf2temeBWlvb0Nc5qHkOgYaRb5QxTZT32GGeN1gtswASOXA==}
+ peerDependencies:
+ '@typescript-eslint/eslint-plugin': ^5.0.0
+ eslint: ^8.0.1
+ eslint-plugin-import: ^2.25.2
+ eslint-plugin-n: ^15.0.0
+ eslint-plugin-promise: ^6.0.0
+ typescript: '*'
+ dependencies:
+ '@typescript-eslint/eslint-plugin': 5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.56.0)(typescript@5.3.3)
+ '@typescript-eslint/parser': 5.62.0(eslint@8.56.0)(typescript@5.3.3)
+ eslint: 8.56.0
+ eslint-config-standard: 17.0.0(eslint-plugin-import@2.29.1)(eslint-plugin-n@15.7.0)(eslint-plugin-promise@6.1.1)(eslint@8.56.0)
+ eslint-plugin-import: 2.29.1(@typescript-eslint/parser@5.62.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0)
+ eslint-plugin-n: 15.7.0(eslint@8.56.0)
+ eslint-plugin-promise: 6.1.1(eslint@8.56.0)
+ typescript: 5.3.3
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /eslint-config-standard-with-typescript@43.0.0(@typescript-eslint/eslint-plugin@6.16.0)(eslint-plugin-import@2.29.1)(eslint-plugin-n@16.5.0)(eslint-plugin-promise@6.1.1)(eslint@8.56.0)(typescript@5.3.3):
+ resolution: {integrity: sha512-AT0qK01M5bmsWiE3UZvaQO5da1y1n6uQckAKqGNe6zPW5IOzgMLXZxw77nnFm+C11nxAZXsCPrbsgJhSrGfX6Q==}
+ peerDependencies:
+ '@typescript-eslint/eslint-plugin': ^6.4.0
+ eslint: ^8.0.1
+ eslint-plugin-import: ^2.25.2
+ eslint-plugin-n: '^15.0.0 || ^16.0.0 '
+ eslint-plugin-promise: ^6.0.0
+ typescript: '*'
+ dependencies:
+ '@typescript-eslint/eslint-plugin': 6.16.0(@typescript-eslint/parser@6.16.0)(eslint@8.56.0)(typescript@5.3.3)
+ '@typescript-eslint/parser': 6.16.0(eslint@8.56.0)(typescript@5.3.3)
+ eslint: 8.56.0
+ eslint-config-standard: 17.1.0(eslint-plugin-import@2.29.1)(eslint-plugin-n@16.5.0)(eslint-plugin-promise@6.1.1)(eslint@8.56.0)
+ eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.16.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0)
+ eslint-plugin-n: 16.5.0(eslint@8.56.0)
+ eslint-plugin-promise: 6.1.1(eslint@8.56.0)
+ typescript: 5.3.3
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /eslint-config-standard@17.0.0(eslint-plugin-import@2.29.1)(eslint-plugin-n@15.7.0)(eslint-plugin-promise@6.1.1)(eslint@8.56.0):
+ resolution: {integrity: sha512-/2ks1GKyqSOkH7JFvXJicu0iMpoojkwB+f5Du/1SC0PtBL+s8v30k9njRZ21pm2drKYm2342jFnGWzttxPmZVg==}
+ peerDependencies:
+ eslint: ^8.0.1
+ eslint-plugin-import: ^2.25.2
+ eslint-plugin-n: ^15.0.0
+ eslint-plugin-promise: ^6.0.0
+ dependencies:
+ eslint: 8.56.0
+ eslint-plugin-import: 2.29.1(@typescript-eslint/parser@5.62.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0)
+ eslint-plugin-n: 15.7.0(eslint@8.56.0)
+ eslint-plugin-promise: 6.1.1(eslint@8.56.0)
+ dev: true
+
+ /eslint-config-standard@17.1.0(eslint-plugin-import@2.29.1)(eslint-plugin-n@16.5.0)(eslint-plugin-promise@6.1.1)(eslint@8.56.0):
+ resolution: {integrity: sha512-IwHwmaBNtDK4zDHQukFDW5u/aTb8+meQWZvNFWkiGmbWjD6bqyuSSBxxXKkCftCUzc1zwCH2m/baCNDLGmuO5Q==}
+ engines: {node: '>=12.0.0'}
+ peerDependencies:
+ eslint: ^8.0.1
+ eslint-plugin-import: ^2.25.2
+ eslint-plugin-n: '^15.0.0 || ^16.0.0 '
+ eslint-plugin-promise: ^6.0.0
+ dependencies:
+ eslint: 8.56.0
+ eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.16.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0)
+ eslint-plugin-n: 16.5.0(eslint@8.56.0)
+ eslint-plugin-promise: 6.1.1(eslint@8.56.0)
+ dev: true
+
+ /eslint-define-config@2.1.0:
+ resolution: {integrity: sha512-QUp6pM9pjKEVannNAbSJNeRuYwW3LshejfyBBpjeMGaJjaDUpVps4C6KVR8R7dWZnD3i0synmrE36znjTkJvdQ==}
+ engines: {node: '>=18.0.0', npm: '>=9.0.0', pnpm: '>=8.6.0'}
+ dev: true
+
/eslint-import-resolver-node@0.3.9:
resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==}
dependencies:
- supports-color
dev: true
+ /eslint-module-utils@2.8.0(@typescript-eslint/parser@5.62.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0):
+ resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==}
+ engines: {node: '>=4'}
+ peerDependencies:
+ '@typescript-eslint/parser': '*'
+ eslint: '*'
+ eslint-import-resolver-node: '*'
+ eslint-import-resolver-typescript: '*'
+ eslint-import-resolver-webpack: '*'
+ peerDependenciesMeta:
+ '@typescript-eslint/parser':
+ optional: true
+ eslint:
+ optional: true
+ eslint-import-resolver-node:
+ optional: true
+ eslint-import-resolver-typescript:
+ optional: true
+ eslint-import-resolver-webpack:
+ optional: true
+ dependencies:
+ '@typescript-eslint/parser': 5.62.0(eslint@8.56.0)(typescript@5.3.3)
+ debug: 3.2.7
+ eslint: 8.56.0
+ eslint-import-resolver-node: 0.3.9
+ eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.16.0)(eslint-plugin-import@2.29.1)(eslint@8.56.0)
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
/eslint-module-utils@2.8.0(@typescript-eslint/parser@6.16.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0):
resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==}
engines: {node: '>=4'}
eslint-compat-utils: 0.1.2(eslint@8.56.0)
dev: true
+ /eslint-plugin-es@4.1.0(eslint@8.56.0):
+ resolution: {integrity: sha512-GILhQTnjYE2WorX5Jyi5i4dz5ALWxBIdQECVQavL6s7cI76IZTDWleTHkxz/QT3kvcs2QlGHvKLYsSlPOlPXnQ==}
+ engines: {node: '>=8.10.0'}
+ peerDependencies:
+ eslint: '>=4.19.1'
+ dependencies:
+ eslint: 8.56.0
+ eslint-utils: 2.1.0
+ regexpp: 3.2.0
+ dev: true
+
+ /eslint-plugin-import@2.29.1(@typescript-eslint/parser@5.62.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0):
+ resolution: {integrity: sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==}
+ engines: {node: '>=4'}
+ peerDependencies:
+ '@typescript-eslint/parser': '*'
+ eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8
+ peerDependenciesMeta:
+ '@typescript-eslint/parser':
+ optional: true
+ dependencies:
+ '@typescript-eslint/parser': 5.62.0(eslint@8.56.0)(typescript@5.3.3)
+ array-includes: 3.1.7
+ array.prototype.findlastindex: 1.2.3
+ array.prototype.flat: 1.3.2
+ array.prototype.flatmap: 1.3.2
+ debug: 3.2.7
+ doctrine: 2.1.0
+ eslint: 8.56.0
+ eslint-import-resolver-node: 0.3.9
+ eslint-module-utils: 2.8.0(@typescript-eslint/parser@5.62.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0)
+ hasown: 2.0.0
+ is-core-module: 2.13.1
+ is-glob: 4.0.3
+ minimatch: 3.1.2
+ object.fromentries: 2.0.7
+ object.groupby: 1.0.1
+ object.values: 1.1.7
+ semver: 7.5.4
+ tsconfig-paths: 3.15.0
+ transitivePeerDependencies:
+ - eslint-import-resolver-typescript
+ - eslint-import-resolver-webpack
+ - supports-color
+ dev: true
+
/eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.16.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0):
resolution: {integrity: sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==}
engines: {node: '>=4'}
- supports-color
dev: true
+ /eslint-plugin-n@15.7.0(eslint@8.56.0):
+ resolution: {integrity: sha512-jDex9s7D/Qial8AGVIHq4W7NswpUD5DPDL2RH8Lzd9EloWUuvUkHfv4FRLMipH5q2UtyurorBkPeNi1wVWNh3Q==}
+ engines: {node: '>=12.22.0'}
+ peerDependencies:
+ eslint: '>=7.0.0'
+ dependencies:
+ builtins: 5.0.1
+ eslint: 8.56.0
+ eslint-plugin-es: 4.1.0(eslint@8.56.0)
+ eslint-utils: 3.0.0(eslint@8.56.0)
+ ignore: 5.3.0
+ is-core-module: 2.13.1
+ minimatch: 3.1.2
+ resolve: 1.22.8
+ semver: 7.5.4
+ dev: true
+
/eslint-plugin-n@16.5.0(eslint@8.56.0):
resolution: {integrity: sha512-Hw02Bj1QrZIlKyj471Tb1jSReTl4ghIMHGuBGiMVmw+s0jOPbI4CBuYpGbZr+tdQ+VAvSK6FDSta3J4ib/SKHQ==}
engines: {node: '>=16.0.0'}
synckit: 0.8.8
dev: true
+ /eslint-plugin-promise@6.1.1(eslint@8.56.0):
+ resolution: {integrity: sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ peerDependencies:
+ eslint: ^7.0.0 || ^8.0.0
+ dependencies:
+ eslint: 8.56.0
+ dev: true
+
+ /eslint-plugin-react@7.33.2(eslint@8.56.0):
+ resolution: {integrity: sha512-73QQMKALArI8/7xGLNI/3LylrEYrlKZSb5C9+q3OtOewTnMQi5cT+aE9E41sLCmli3I9PGGmD1yiZydyo4FEPw==}
+ engines: {node: '>=4'}
+ peerDependencies:
+ eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8
+ dependencies:
+ array-includes: 3.1.7
+ array.prototype.flatmap: 1.3.2
+ array.prototype.tosorted: 1.1.2
+ doctrine: 2.1.0
+ es-iterator-helpers: 1.0.15
+ eslint: 8.56.0
+ estraverse: 5.3.0
+ jsx-ast-utils: 3.3.5
+ minimatch: 3.1.2
+ object.entries: 1.1.7
+ object.fromentries: 2.0.7
+ object.hasown: 1.1.3
+ object.values: 1.1.7
+ prop-types: 15.8.1
+ resolve: 2.0.0-next.5
+ semver: 7.5.4
+ string.prototype.matchall: 4.0.10
+ dev: true
+
/eslint-plugin-tsdoc@0.2.17:
resolution: {integrity: sha512-xRmVi7Zx44lOBuYqG8vzTXuL6IdGOeF9nHX17bjJ8+VE6fsxpdGem0/SBTmAwgYMKYB1WBkqRJVQ+n8GK041pA==}
dependencies:
'@microsoft/tsdoc-config': 0.16.2
dev: true
+ /eslint-scope@5.1.1:
+ resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==}
+ engines: {node: '>=8.0.0'}
+ dependencies:
+ esrecurse: 4.3.0
+ estraverse: 4.3.0
+ dev: true
+
/eslint-scope@7.2.2:
resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
estraverse: 5.3.0
dev: true
+ /eslint-utils@2.1.0:
+ resolution: {integrity: sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==}
+ engines: {node: '>=6'}
+ dependencies:
+ eslint-visitor-keys: 1.3.0
+ dev: true
+
+ /eslint-utils@3.0.0(eslint@8.56.0):
+ resolution: {integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==}
+ engines: {node: ^10.0.0 || ^12.0.0 || >= 14.0.0}
+ peerDependencies:
+ eslint: '>=5'
+ dependencies:
+ eslint: 8.56.0
+ eslint-visitor-keys: 2.1.0
+ dev: true
+
+ /eslint-visitor-keys@1.3.0:
+ resolution: {integrity: sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==}
+ engines: {node: '>=4'}
+ dev: true
+
+ /eslint-visitor-keys@2.1.0:
+ resolution: {integrity: sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==}
+ engines: {node: '>=10'}
+ dev: true
+
/eslint-visitor-keys@3.4.3:
resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
path-exists: 4.0.0
dev: true
+ /find-up@6.3.0:
+ resolution: {integrity: sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+ dependencies:
+ locate-path: 7.2.0
+ path-exists: 5.0.0
+ dev: true
+
/flame-gradient@1.0.0:
resolution: {integrity: sha512-9ejk16/DqvQJ4dHsh68W/4N0zmVQ60zukyUuEHrTbf5pJvP4JqlIdke86Z9174PZokRCXAntY5+H1txSyC7mUA==}
dependencies:
resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==}
engines: {node: '>=8.0.0'}
+ /get-stdin@8.0.0:
+ resolution: {integrity: sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==}
+ engines: {node: '>=10'}
+ dev: true
+
/get-stream@5.2.0:
resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==}
engines: {node: '>=8'}
resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==}
dev: false
+ /is-async-function@2.0.0:
+ resolution: {integrity: sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ has-tostringtag: 1.0.0
+ dev: true
+
/is-bigint@1.0.4:
resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==}
dependencies:
resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
engines: {node: '>=0.10.0'}
+ /is-finalizationregistry@1.0.2:
+ resolution: {integrity: sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==}
+ dependencies:
+ call-bind: 1.0.5
+ dev: true
+
/is-fullwidth-code-point@1.0.0:
resolution: {integrity: sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==}
engines: {node: '>=0.10.0'}
engines: {node: '>=12'}
dev: true
+ /is-weakmap@2.0.1:
+ resolution: {integrity: sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==}
+ dev: true
+
/is-weakref@1.0.2:
resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==}
dependencies:
call-bind: 1.0.5
dev: true
+ /is-weakset@2.0.2:
+ resolution: {integrity: sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==}
+ dependencies:
+ call-bind: 1.0.5
+ get-intrinsic: 1.2.2
+ dev: true
+
/is-wsl@1.1.0:
resolution: {integrity: sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw==}
engines: {node: '>=4'}
iterate-iterator: 1.0.2
dev: true
+ /iterator.prototype@1.1.2:
+ resolution: {integrity: sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==}
+ dependencies:
+ define-properties: 1.2.1
+ get-intrinsic: 1.2.2
+ has-symbols: 1.0.3
+ reflect.getprototypeof: 1.0.4
+ set-function-name: 2.0.1
+ dev: true
+
/jackspeak@2.3.6:
resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==}
engines: {node: '>=14'}
resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==}
dev: true
+ /json-parse-better-errors@1.0.2:
+ resolution: {integrity: sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==}
+ dev: true
+
/json-parse-even-better-errors@2.3.1:
resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==}
dev: true
verror: 1.10.0
dev: true
+ /jsx-ast-utils@3.3.5:
+ resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==}
+ engines: {node: '>=4.0'}
+ dependencies:
+ array-includes: 3.1.7
+ array.prototype.flat: 1.3.2
+ object.assign: 4.1.5
+ object.values: 1.1.7
+ dev: true
+
/just-merge@3.2.0:
resolution: {integrity: sha512-cNh5FWt44hx4SpQS1xZU8Tzr/fQA69pqCdjbwxmaYYIOuRfA8EIg+dn1bGmIW03ZUtR2vkMOCjWKc+jIbpauSw==}
dev: false
wrap-ansi: 9.0.0
dev: true
+ /load-json-file@5.3.0:
+ resolution: {integrity: sha512-cJGP40Jc/VXUsp8/OrnyKyTZ1y6v/dphm3bioS+RrKXjK2BB6wHUd6JptZEFDGgGahMT+InnZO5i1Ei9mpC8Bw==}
+ engines: {node: '>=6'}
+ dependencies:
+ graceful-fs: 4.2.11
+ parse-json: 4.0.0
+ pify: 4.0.1
+ strip-bom: 3.0.0
+ type-fest: 0.3.1
+ dev: true
+
+ /load-json-file@7.0.1:
+ resolution: {integrity: sha512-Gnxj3ev3mB5TkVBGad0JM6dmLiQL+o0t23JPBZ9sd+yvSLk05mFoqKBw5N8gbbkU4TNXyqCgIrl/VM17OgUIgQ==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+ dev: true
+
/locate-path@3.0.0:
resolution: {integrity: sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==}
engines: {node: '>=6'}
p-locate: 5.0.0
dev: true
+ /locate-path@7.2.0:
+ resolution: {integrity: sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+ dependencies:
+ p-locate: 6.0.0
+ dev: true
+
/lodash-es@4.17.21:
resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==}
dev: true
semver: 7.5.4
dev: true
+ /make-error@1.3.6:
+ resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==}
+ dev: true
+
/make-fetch-happen@9.1.0:
resolution: {integrity: sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==}
engines: {node: '>= 10'}
hasBin: true
dev: true
+ /natural-compare-lite@1.4.0:
+ resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==}
+ dev: true
+
/natural-compare@1.4.0:
resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
dev: true
object-keys: 1.1.1
dev: true
+ /object.entries@1.1.7:
+ resolution: {integrity: sha512-jCBs/0plmPsOnrKAfFQXRG2NFjlhZgjjcBLSmTnEhU8U6vVTsVe8ANeQJCHTl3gSsI4J+0emOoCgoKlmQPMgmA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ es-abstract: 1.22.3
+ dev: true
+
/object.fromentries@2.0.7:
resolution: {integrity: sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==}
engines: {node: '>= 0.4'}
get-intrinsic: 1.2.2
dev: true
+ /object.hasown@1.1.3:
+ resolution: {integrity: sha512-fFI4VcYpRHvSLXxP7yiZOMAd331cPfd2p7PFDVbgUsYOfCT3tICVqXWngbjr4m49OvsBwUBQ6O2uQoJvy3RexA==}
+ dependencies:
+ define-properties: 1.2.1
+ es-abstract: 1.22.3
+ dev: true
+
/object.values@1.1.7:
resolution: {integrity: sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==}
engines: {node: '>= 0.4'}
yocto-queue: 0.1.0
dev: true
+ /p-limit@4.0.0:
+ resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+ dependencies:
+ yocto-queue: 1.0.0
+ dev: true
+
/p-locate@3.0.0:
resolution: {integrity: sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==}
engines: {node: '>=6'}
p-limit: 3.1.0
dev: true
+ /p-locate@6.0.0:
+ resolution: {integrity: sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+ dependencies:
+ p-limit: 4.0.0
+ dev: true
+
/p-map@4.0.0:
resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==}
engines: {node: '>=10'}
hasBin: true
dev: true
+ /parse-json@4.0.0:
+ resolution: {integrity: sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==}
+ engines: {node: '>=4'}
+ dependencies:
+ error-ex: 1.3.2
+ json-parse-better-errors: 1.0.2
+ dev: true
+
/parse-json@5.2.0:
resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==}
engines: {node: '>=8'}
engines: {node: '>=8'}
dev: true
+ /path-exists@5.0.0:
+ resolution: {integrity: sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+ dev: true
+
/path-is-absolute@1.0.1:
resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
engines: {node: '>=0.10.0'}
engines: {node: '>=0.10.0'}
dev: true
+ /pify@4.0.1:
+ resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==}
+ engines: {node: '>=6'}
+ dev: true
+
+ /pkg-conf@3.1.0:
+ resolution: {integrity: sha512-m0OTbR/5VPNPqO1ph6Fqbj7Hv6QU7gR/tQW40ZqrL1rjgCU85W6C1bJn0BItuJqnR98PWzw7Z8hHeChD1WrgdQ==}
+ engines: {node: '>=6'}
+ dependencies:
+ find-up: 3.0.0
+ load-json-file: 5.3.0
+ dev: true
+
+ /pkg-conf@4.0.0:
+ resolution: {integrity: sha512-7dmgi4UY4qk+4mj5Cd8v/GExPo0K+SlY+hulOSdfZ/T6jVH6//y7NtzZo5WrfhDBxuQ0jCa7fLZmNaNh7EWL/w==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+ dependencies:
+ find-up: 6.3.0
+ load-json-file: 7.0.1
+ dev: true
+
/pkg-up@3.1.0:
resolution: {integrity: sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==}
engines: {node: '>=8'}
iterate-value: 1.0.2
dev: true
+ /prop-types@15.8.1:
+ resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==}
+ dependencies:
+ loose-envify: 1.4.0
+ object-assign: 4.1.1
+ react-is: 16.13.1
+ dev: true
+
/proto-list@1.2.4:
resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==}
dev: true
strip-json-comments: 2.0.1
dev: true
+ /react-is@16.13.1:
+ resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
+ dev: true
+
/react-is@18.2.0:
resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==}
dev: true
/reflect-metadata@0.1.13:
resolution: {integrity: sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==}
+ /reflect.getprototypeof@1.0.4:
+ resolution: {integrity: sha512-ECkTw8TmJwW60lOTR+ZkODISW6RQ8+2CL3COqtiJKLd6MmB45hN51HprHFziKLGkAuTGQhBb91V8cy+KHlaCjw==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ es-abstract: 1.22.3
+ get-intrinsic: 1.2.2
+ globalthis: 1.0.3
+ which-builtin-type: 1.1.3
+ dev: true
+
/regexp.prototype.flags@1.5.1:
resolution: {integrity: sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==}
engines: {node: '>= 0.4'}
set-function-name: 2.0.1
dev: true
+ /regexpp@3.2.0:
+ resolution: {integrity: sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==}
+ engines: {node: '>=8'}
+ dev: true
+
/registry-auth-token@4.2.2:
resolution: {integrity: sha512-PC5ZysNb42zpFME6D/XlIgtNGdTl8bBOCw90xQLVMpzuuubJKYDWFAEuUNc+Cn8Z8724tg2SDhDRrkVEsqfDMg==}
engines: {node: '>=6.0.0'}
path-parse: 1.0.7
supports-preserve-symlinks-flag: 1.0.0
+ /resolve@2.0.0-next.5:
+ resolution: {integrity: sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==}
+ hasBin: true
+ dependencies:
+ is-core-module: 2.13.1
+ path-parse: 1.0.7
+ supports-preserve-symlinks-flag: 1.0.0
+ dev: true
+
/responselike@3.0.0:
resolution: {integrity: sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==}
engines: {node: '>=14.16'}
escape-string-regexp: 2.0.0
dev: true
+ /standard-engine@15.1.0:
+ resolution: {integrity: sha512-VHysfoyxFu/ukT+9v49d4BRXIokFRZuH3z1VRxzFArZdjSCFpro6rEIU3ji7e4AoAtuSfKBkiOmsrDqKW5ZSRw==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ dependencies:
+ get-stdin: 8.0.0
+ minimist: 1.2.8
+ pkg-conf: 3.1.0
+ xdg-basedir: 4.0.0
+ dev: true
+
/static-eval@2.1.0:
resolution: {integrity: sha512-agtxZ/kWSsCkI5E4QifRwsaPs0P0JmZV6dkLz6ILYfFYQGn+5plctanRN+IC8dJRiFkyXHrwEE3W9Wmx67uDbw==}
dependencies:
strip-ansi: 7.1.0
dev: true
+ /string.prototype.matchall@4.0.10:
+ resolution: {integrity: sha512-rGXbGmOEosIQi6Qva94HUjgPs9vKW+dkG7Y8Q5O2OYkWL6wFaTRZO8zM4mhP94uX55wgyrXzfS2aGtGzUL7EJQ==}
+ dependencies:
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ es-abstract: 1.22.3
+ get-intrinsic: 1.2.2
+ has-symbols: 1.0.3
+ internal-slot: 1.0.6
+ regexp.prototype.flags: 1.5.1
+ set-function-name: 2.0.1
+ side-channel: 1.0.4
+ dev: true
+
/string.prototype.trim@1.2.8:
resolution: {integrity: sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==}
engines: {node: '>= 0.4'}
code-block-writer: 12.0.0
dev: false
+ /ts-node@10.9.2(@types/node@20.10.5)(typescript@5.3.3):
+ resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==}
+ hasBin: true
+ peerDependencies:
+ '@swc/core': '>=1.2.50'
+ '@swc/wasm': '>=1.2.50'
+ '@types/node': '*'
+ typescript: '>=2.7'
+ peerDependenciesMeta:
+ '@swc/core':
+ optional: true
+ '@swc/wasm':
+ optional: true
+ dependencies:
+ '@cspotcode/source-map-support': 0.8.1
+ '@tsconfig/node10': 1.0.9
+ '@tsconfig/node12': 1.0.11
+ '@tsconfig/node14': 1.0.3
+ '@tsconfig/node16': 1.0.4
+ '@types/node': 20.10.5
+ acorn: 8.11.2
+ acorn-walk: 8.2.0
+ arg: 4.1.3
+ create-require: 1.1.1
+ diff: 4.0.2
+ make-error: 1.3.6
+ typescript: 5.3.3
+ v8-compile-cache-lib: 3.0.1
+ yn: 3.1.1
+ dev: true
+
+ /ts-standard@12.0.2(eslint-import-resolver-typescript@3.6.1)(typescript@5.3.3):
+ resolution: {integrity: sha512-XX2wrB9fKKTfBj4yD3ABm9iShzZcS2iWcPK8XzlBvuL20+wMiLgiz/k5tXgZwTaYq5wRhbks1Y9PelhujF/9ag==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ hasBin: true
+ peerDependencies:
+ typescript: '*'
+ dependencies:
+ '@typescript-eslint/eslint-plugin': 5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.56.0)(typescript@5.3.3)
+ '@typescript-eslint/parser': 5.62.0(eslint@8.56.0)(typescript@5.3.3)
+ eslint: 8.56.0
+ eslint-config-standard-jsx: 11.0.0(eslint-plugin-react@7.33.2)(eslint@8.56.0)
+ eslint-config-standard-with-typescript: 23.0.0(@typescript-eslint/eslint-plugin@5.62.0)(eslint-plugin-import@2.29.1)(eslint-plugin-n@15.7.0)(eslint-plugin-promise@6.1.1)(eslint@8.56.0)(typescript@5.3.3)
+ eslint-plugin-import: 2.29.1(@typescript-eslint/parser@5.62.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0)
+ eslint-plugin-n: 15.7.0(eslint@8.56.0)
+ eslint-plugin-promise: 6.1.1(eslint@8.56.0)
+ eslint-plugin-react: 7.33.2(eslint@8.56.0)
+ minimist: 1.2.8
+ pkg-conf: 4.0.0
+ standard-engine: 15.1.0
+ typescript: 5.3.3
+ transitivePeerDependencies:
+ - eslint-import-resolver-typescript
+ - eslint-import-resolver-webpack
+ - supports-color
+ dev: true
+
/tsconfig-paths@3.15.0:
resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==}
dependencies:
/tslib@2.6.2:
resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==}
+ /tsutils@3.21.0(typescript@5.3.3):
+ resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==}
+ engines: {node: '>= 6'}
+ peerDependencies:
+ typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta'
+ dependencies:
+ tslib: 1.14.1
+ typescript: 5.3.3
+ dev: true
+
/tsx@4.7.0:
resolution: {integrity: sha512-I+t79RYPlEYlHn9a+KzwrvEwhJg35h/1zHsLC2JXvhC2mdynMv6Zxzvhv5EMV6VF5qJlLlkSnMVvdZV3PSIGcg==}
engines: {node: '>=18.0.0'}
engines: {node: '>=10'}
dev: true
+ /type-fest@0.3.1:
+ resolution: {integrity: sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==}
+ engines: {node: '>=6'}
+ dev: true
+
/type-fest@0.6.0:
resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==}
engines: {node: '>=8'}
hasBin: true
dev: true
+ /v8-compile-cache-lib@3.0.1:
+ resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==}
+ dev: true
+
/v8-to-istanbul@9.2.0:
resolution: {integrity: sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA==}
engines: {node: '>=10.12.0'}
is-symbol: 1.0.4
dev: true
+ /which-builtin-type@1.1.3:
+ resolution: {integrity: sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ function.prototype.name: 1.1.6
+ has-tostringtag: 1.0.0
+ is-async-function: 2.0.0
+ is-date-object: 1.0.5
+ is-finalizationregistry: 1.0.2
+ is-generator-function: 1.0.10
+ is-regex: 1.1.4
+ is-weakref: 1.0.2
+ isarray: 2.0.5
+ which-boxed-primitive: 1.0.2
+ which-collection: 1.0.1
+ which-typed-array: 1.1.13
+ dev: true
+
+ /which-collection@1.0.1:
+ resolution: {integrity: sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==}
+ dependencies:
+ is-map: 2.0.2
+ is-set: 2.0.2
+ is-weakmap: 2.0.1
+ is-weakset: 2.0.2
+ dev: true
+
/which-module@2.0.1:
resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==}
dev: true
yargs-parser: 21.1.1
dev: true
+ /yn@3.1.1:
+ resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==}
+ engines: {node: '>=6'}
+ dev: true
+
/yocto-queue@0.1.0:
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
engines: {node: '>=10'}
dev: true
+
+ /yocto-queue@1.0.0:
+ resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==}
+ engines: {node: '>=12.20'}
+ dev: true
-import { env } from 'node:process';
+import { env } from 'node:process'
-const isCIEnvironment = env.CI !== undefined;
-const isCFEnvironment = env.VCAP_APPLICATION !== undefined;
+const isCIEnvironment = env.CI !== undefined
+const isCFEnvironment = env.VCAP_APPLICATION !== undefined
if (isCFEnvironment === false && isCIEnvironment === false) {
// eslint-disable-next-line n/no-unpublished-import
- import('husky').then(({ install }) => install());
+ import('husky').then(({ install }) => install())
}
-import { env, exit } from 'node:process';
+import { env, exit } from 'node:process'
-const skipPreinstall = env.SKIP_PREINSTALL || env.VCAP_APPLICATION !== undefined;
+const skipPreinstall = env.SKIP_PREINSTALL || env.VCAP_APPLICATION !== undefined
if (skipPreinstall) {
// eslint-disable-next-line n/no-process-exit
- exit();
+ exit()
} else {
// eslint-disable-next-line n/no-process-exit
- exit(1);
+ exit(1)
}
// Partial Copyright Jerome Benoit. 2021-2023. All Rights Reserved.
-import { hoursToMilliseconds, secondsToMilliseconds } from 'date-fns';
+import { hoursToMilliseconds, secondsToMilliseconds } from 'date-fns'
-import type { ChargingStation } from './ChargingStation.js';
-import { checkChargingStation } from './Helpers.js';
-import { IdTagsCache } from './IdTagsCache.js';
-import { isIdTagAuthorized } from './ocpp/index.js';
-import { BaseError } from '../exception/index.js';
-import { PerformanceStatistics } from '../performance/index.js';
+import type { ChargingStation } from './ChargingStation.js'
+import { checkChargingStation } from './Helpers.js'
+import { IdTagsCache } from './IdTagsCache.js'
+import { isIdTagAuthorized } from './ocpp/index.js'
+import { BaseError } from '../exception/index.js'
+import { PerformanceStatistics } from '../performance/index.js'
import {
AuthorizationStatus,
RequestCommand,
type StartTransactionResponse,
type Status,
StopTransactionReason,
- type StopTransactionResponse,
-} from '../types/index.js';
+ type StopTransactionResponse
+} from '../types/index.js'
import {
Constants,
cloneObject,
logPrefix,
logger,
secureRandom,
- sleep,
-} from '../utils/index.js';
+ sleep
+} from '../utils/index.js'
export class AutomaticTransactionGenerator {
private static readonly instances: Map<string, AutomaticTransactionGenerator> = new Map<
- string,
- AutomaticTransactionGenerator
- >();
+ string,
+ AutomaticTransactionGenerator
+ >()
- public readonly connectorsStatus: Map<number, Status>;
- public started: boolean;
- private starting: boolean;
- private stopping: boolean;
- private readonly chargingStation: ChargingStation;
+ public readonly connectorsStatus: Map<number, Status>
+ public started: boolean
+ private starting: boolean
+ private stopping: boolean
+ private readonly chargingStation: ChargingStation
- private constructor(chargingStation: ChargingStation) {
- this.started = false;
- this.starting = false;
- this.stopping = false;
- this.chargingStation = chargingStation;
- this.connectorsStatus = new Map<number, Status>();
- this.initializeConnectorsStatus();
+ private constructor (chargingStation: ChargingStation) {
+ this.started = false
+ this.starting = false
+ this.stopping = false
+ this.chargingStation = chargingStation
+ this.connectorsStatus = new Map<number, Status>()
+ this.initializeConnectorsStatus()
}
- public static getInstance(
- chargingStation: ChargingStation,
+ public static getInstance (
+ chargingStation: ChargingStation
): AutomaticTransactionGenerator | undefined {
- if (AutomaticTransactionGenerator.instances.has(chargingStation.stationInfo.hashId) === false) {
+ if (!AutomaticTransactionGenerator.instances.has(chargingStation.stationInfo.hashId)) {
AutomaticTransactionGenerator.instances.set(
chargingStation.stationInfo.hashId,
- new AutomaticTransactionGenerator(chargingStation),
- );
+ new AutomaticTransactionGenerator(chargingStation)
+ )
}
- return AutomaticTransactionGenerator.instances.get(chargingStation.stationInfo.hashId);
+ return AutomaticTransactionGenerator.instances.get(chargingStation.stationInfo.hashId)
}
- public start(): void {
- if (checkChargingStation(this.chargingStation, this.logPrefix()) === false) {
- return;
+ public start (): void {
+ if (!checkChargingStation(this.chargingStation, this.logPrefix())) {
+ return
}
- if (this.started === true) {
- logger.warn(`${this.logPrefix()} is already started`);
- return;
+ if (this.started) {
+ logger.warn(`${this.logPrefix()} is already started`)
+ return
}
- if (this.starting === true) {
- logger.warn(`${this.logPrefix()} is already starting`);
- return;
+ if (this.starting) {
+ logger.warn(`${this.logPrefix()} is already starting`)
+ return
}
- this.starting = true;
- this.startConnectors();
- this.started = true;
- this.starting = false;
+ this.starting = true
+ this.startConnectors()
+ this.started = true
+ this.starting = false
}
- public stop(): void {
- if (this.started === false) {
- logger.warn(`${this.logPrefix()} is already stopped`);
- return;
+ public stop (): void {
+ if (!this.started) {
+ logger.warn(`${this.logPrefix()} is already stopped`)
+ return
}
- if (this.stopping === true) {
- logger.warn(`${this.logPrefix()} is already stopping`);
- return;
+ if (this.stopping) {
+ logger.warn(`${this.logPrefix()} is already stopping`)
+ return
}
- this.stopping = true;
- this.stopConnectors();
- this.started = false;
- this.stopping = false;
+ this.stopping = true
+ this.stopConnectors()
+ this.started = false
+ this.stopping = false
}
- public startConnector(connectorId: number): void {
- if (checkChargingStation(this.chargingStation, this.logPrefix(connectorId)) === false) {
- return;
+ public startConnector (connectorId: number): void {
+ if (!checkChargingStation(this.chargingStation, this.logPrefix(connectorId))) {
+ return
}
- if (this.connectorsStatus.has(connectorId) === false) {
- logger.error(`${this.logPrefix(connectorId)} starting on non existing connector`);
- throw new BaseError(`Connector ${connectorId} does not exist`);
+ if (!this.connectorsStatus.has(connectorId)) {
+ logger.error(`${this.logPrefix(connectorId)} starting on non existing connector`)
+ throw new BaseError(`Connector ${connectorId} does not exist`)
}
if (this.connectorsStatus.get(connectorId)?.start === false) {
- this.internalStartConnector(connectorId).catch(Constants.EMPTY_FUNCTION);
+ this.internalStartConnector(connectorId).catch(Constants.EMPTY_FUNCTION)
} else if (this.connectorsStatus.get(connectorId)?.start === true) {
- logger.warn(`${this.logPrefix(connectorId)} is already started on connector`);
+ logger.warn(`${this.logPrefix(connectorId)} is already started on connector`)
}
}
- public stopConnector(connectorId: number): void {
- if (this.connectorsStatus.has(connectorId) === false) {
- logger.error(`${this.logPrefix(connectorId)} stopping on non existing connector`);
- throw new BaseError(`Connector ${connectorId} does not exist`);
+ public stopConnector (connectorId: number): void {
+ if (!this.connectorsStatus.has(connectorId)) {
+ logger.error(`${this.logPrefix(connectorId)} stopping on non existing connector`)
+ throw new BaseError(`Connector ${connectorId} does not exist`)
}
if (this.connectorsStatus.get(connectorId)?.start === true) {
- this.connectorsStatus.get(connectorId)!.start = false;
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ this.connectorsStatus.get(connectorId)!.start = false
} else if (this.connectorsStatus.get(connectorId)?.start === false) {
- logger.warn(`${this.logPrefix(connectorId)} is already stopped on connector`);
+ logger.warn(`${this.logPrefix(connectorId)} is already stopped on connector`)
}
}
- private startConnectors(): void {
+ private startConnectors (): void {
if (
this.connectorsStatus?.size > 0 &&
this.connectorsStatus.size !== this.chargingStation.getNumberOfConnectors()
) {
- this.connectorsStatus.clear();
- this.initializeConnectorsStatus();
+ this.connectorsStatus.clear()
+ this.initializeConnectorsStatus()
}
if (this.chargingStation.hasEvses) {
for (const [evseId, evseStatus] of this.chargingStation.evses) {
if (evseId > 0) {
for (const connectorId of evseStatus.connectors.keys()) {
- this.startConnector(connectorId);
+ this.startConnector(connectorId)
}
}
}
} else {
for (const connectorId of this.chargingStation.connectors.keys()) {
if (connectorId > 0) {
- this.startConnector(connectorId);
+ this.startConnector(connectorId)
}
}
}
}
- private stopConnectors(): void {
+ private stopConnectors (): void {
if (this.chargingStation.hasEvses) {
for (const [evseId, evseStatus] of this.chargingStation.evses) {
if (evseId > 0) {
for (const connectorId of evseStatus.connectors.keys()) {
- this.stopConnector(connectorId);
+ this.stopConnector(connectorId)
}
}
}
} else {
for (const connectorId of this.chargingStation.connectors.keys()) {
if (connectorId > 0) {
- this.stopConnector(connectorId);
+ this.stopConnector(connectorId)
}
}
}
}
- private async internalStartConnector(connectorId: number): Promise<void> {
- this.setStartConnectorStatus(connectorId);
+ private async internalStartConnector (connectorId: number): Promise<void> {
+ this.setStartConnectorStatus(connectorId)
logger.info(
`${this.logPrefix(
- connectorId,
+ connectorId
)} started on connector and will run for ${formatDurationMilliSeconds(
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.connectorsStatus.get(connectorId)!.stopDate!.getTime() -
- this.connectorsStatus.get(connectorId)!.startDate!.getTime(),
- )}`,
- );
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ this.connectorsStatus.get(connectorId)!.startDate!.getTime()
+ )}`
+ )
while (this.connectorsStatus.get(connectorId)?.start === true) {
- await this.waitChargingStationServiceInitialization(connectorId);
- await this.waitChargingStationAvailable(connectorId);
- await this.waitConnectorAvailable(connectorId);
+ await this.waitChargingStationServiceInitialization(connectorId)
+ await this.waitChargingStationAvailable(connectorId)
+ await this.waitConnectorAvailable(connectorId)
if (!this.canStartConnector(connectorId)) {
- this.stopConnector(connectorId);
- break;
+ this.stopConnector(connectorId)
+ break
}
const wait = secondsToMilliseconds(
getRandomInteger(
this.chargingStation.getAutomaticTransactionGeneratorConfiguration()
.maxDelayBetweenTwoTransactions,
this.chargingStation.getAutomaticTransactionGeneratorConfiguration()
- .minDelayBetweenTwoTransactions,
- ),
- );
- logger.info(`${this.logPrefix(connectorId)} waiting for ${formatDurationMilliSeconds(wait)}`);
- await sleep(wait);
- const start = secureRandom();
+ .minDelayBetweenTwoTransactions
+ )
+ )
+ logger.info(`${this.logPrefix(connectorId)} waiting for ${formatDurationMilliSeconds(wait)}`)
+ await sleep(wait)
+ const start = secureRandom()
if (
start <
this.chargingStation.getAutomaticTransactionGeneratorConfiguration().probabilityOfStart
) {
- this.connectorsStatus.get(connectorId)!.skippedConsecutiveTransactions = 0;
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ this.connectorsStatus.get(connectorId)!.skippedConsecutiveTransactions = 0
// Start transaction
- const startResponse = await this.startTransaction(connectorId);
+ const startResponse = await this.startTransaction(connectorId)
if (startResponse?.idTagInfo?.status === AuthorizationStatus.ACCEPTED) {
// Wait until end of transaction
const waitTrxEnd = secondsToMilliseconds(
getRandomInteger(
this.chargingStation.getAutomaticTransactionGeneratorConfiguration().maxDuration,
- this.chargingStation.getAutomaticTransactionGeneratorConfiguration().minDuration,
- ),
- );
+ this.chargingStation.getAutomaticTransactionGeneratorConfiguration().minDuration
+ )
+ )
logger.info(
`${this.logPrefix(
- connectorId,
+ connectorId
)} transaction started with id ${this.chargingStation.getConnectorStatus(connectorId)
- ?.transactionId} and will stop in ${formatDurationMilliSeconds(waitTrxEnd)}`,
- );
- await sleep(waitTrxEnd);
- await this.stopTransaction(connectorId);
+ ?.transactionId} and will stop in ${formatDurationMilliSeconds(waitTrxEnd)}`
+ )
+ await sleep(waitTrxEnd)
+ await this.stopTransaction(connectorId)
}
} else {
- ++this.connectorsStatus.get(connectorId)!.skippedConsecutiveTransactions!;
- ++this.connectorsStatus.get(connectorId)!.skippedTransactions!;
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ ++this.connectorsStatus.get(connectorId)!.skippedConsecutiveTransactions!
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ ++this.connectorsStatus.get(connectorId)!.skippedTransactions!
logger.info(
`${this.logPrefix(connectorId)} skipped consecutively ${this.connectorsStatus.get(
- connectorId,
+ connectorId
)?.skippedConsecutiveTransactions}/${this.connectorsStatus.get(connectorId)
- ?.skippedTransactions} transaction(s)`,
- );
+ ?.skippedTransactions} transaction(s)`
+ )
}
- this.connectorsStatus.get(connectorId)!.lastRunDate = new Date();
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ this.connectorsStatus.get(connectorId)!.lastRunDate = new Date()
}
- this.connectorsStatus.get(connectorId)!.stoppedDate = new Date();
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ this.connectorsStatus.get(connectorId)!.stoppedDate = new Date()
logger.info(
`${this.logPrefix(
- connectorId,
+ connectorId
)} stopped on connector and lasted for ${formatDurationMilliSeconds(
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.connectorsStatus.get(connectorId)!.stoppedDate!.getTime() -
- this.connectorsStatus.get(connectorId)!.startDate!.getTime(),
- )}`,
- );
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ this.connectorsStatus.get(connectorId)!.startDate!.getTime()
+ )}`
+ )
logger.debug(
`${this.logPrefix(connectorId)} connector status: %j`,
- this.connectorsStatus.get(connectorId),
- );
+ this.connectorsStatus.get(connectorId)
+ )
}
- private setStartConnectorStatus(connectorId: number): void {
- this.connectorsStatus.get(connectorId)!.skippedConsecutiveTransactions = 0;
+ private setStartConnectorStatus (connectorId: number): void {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ this.connectorsStatus.get(connectorId)!.skippedConsecutiveTransactions = 0
const previousRunDuration =
- this.connectorsStatus.get(connectorId)?.startDate &&
- this.connectorsStatus.get(connectorId)?.lastRunDate
- ? this.connectorsStatus.get(connectorId)!.lastRunDate!.getTime() -
+ this.connectorsStatus.get(connectorId)?.startDate != null &&
+ this.connectorsStatus.get(connectorId)?.lastRunDate != null
+ ? // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ this.connectorsStatus.get(connectorId)!.lastRunDate!.getTime() -
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.connectorsStatus.get(connectorId)!.startDate!.getTime()
- : 0;
- this.connectorsStatus.get(connectorId)!.startDate = new Date();
+ : 0
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ this.connectorsStatus.get(connectorId)!.startDate = new Date()
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.connectorsStatus.get(connectorId)!.stopDate = new Date(
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.connectorsStatus.get(connectorId)!.startDate!.getTime() +
hoursToMilliseconds(
- this.chargingStation.getAutomaticTransactionGeneratorConfiguration().stopAfterHours,
+ this.chargingStation.getAutomaticTransactionGeneratorConfiguration().stopAfterHours
) -
- previousRunDuration,
- );
- this.connectorsStatus.get(connectorId)!.start = true;
+ previousRunDuration
+ )
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ this.connectorsStatus.get(connectorId)!.start = true
}
- private canStartConnector(connectorId: number): boolean {
+ private canStartConnector (connectorId: number): boolean {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
if (new Date() > this.connectorsStatus.get(connectorId)!.stopDate!) {
- return false;
+ return false
}
- if (this.chargingStation.inAcceptedState() === false) {
+ if (!this.chargingStation.inAcceptedState()) {
logger.error(
`${this.logPrefix(
- connectorId,
- )} entered in transaction loop while the charging station is not in accepted state`,
- );
- return false;
+ connectorId
+ )} entered in transaction loop while the charging station is not in accepted state`
+ )
+ return false
}
- if (this.chargingStation.isChargingStationAvailable() === false) {
+ if (!this.chargingStation.isChargingStationAvailable()) {
logger.info(
`${this.logPrefix(
- connectorId,
- )} entered in transaction loop while the charging station is unavailable`,
- );
- return false;
+ connectorId
+ )} entered in transaction loop while the charging station is unavailable`
+ )
+ return false
}
- if (this.chargingStation.isConnectorAvailable(connectorId) === false) {
+ if (!this.chargingStation.isConnectorAvailable(connectorId)) {
logger.info(
`${this.logPrefix(
- connectorId,
- )} entered in transaction loop while the connector ${connectorId} is unavailable`,
- );
- return false;
+ connectorId
+ )} entered in transaction loop while the connector ${connectorId} is unavailable`
+ )
+ return false
}
- return true;
+ return true
}
- private async waitChargingStationServiceInitialization(connectorId: number): Promise<void> {
- let logged = false;
- while (!this.chargingStation?.ocppRequestService) {
+ private async waitChargingStationServiceInitialization (connectorId: number): Promise<void> {
+ let logged = false
+ while (this.chargingStation?.ocppRequestService == null) {
if (!logged) {
logger.info(
`${this.logPrefix(
- connectorId,
- )} transaction loop waiting for charging station service to be initialized`,
- );
- logged = true;
+ connectorId
+ )} transaction loop waiting for charging station service to be initialized`
+ )
+ logged = true
}
- await sleep(Constants.CHARGING_STATION_ATG_INITIALIZATION_TIME);
+ await sleep(Constants.CHARGING_STATION_ATG_INITIALIZATION_TIME)
}
}
- private async waitChargingStationAvailable(connectorId: number): Promise<void> {
- let logged = false;
+ private async waitChargingStationAvailable (connectorId: number): Promise<void> {
+ let logged = false
while (!this.chargingStation.isChargingStationAvailable()) {
if (!logged) {
logger.info(
`${this.logPrefix(
- connectorId,
- )} transaction loop waiting for charging station to be available`,
- );
- logged = true;
+ connectorId
+ )} transaction loop waiting for charging station to be available`
+ )
+ logged = true
}
- await sleep(Constants.CHARGING_STATION_ATG_AVAILABILITY_TIME);
+ await sleep(Constants.CHARGING_STATION_ATG_AVAILABILITY_TIME)
}
}
- private async waitConnectorAvailable(connectorId: number): Promise<void> {
- let logged = false;
+ private async waitConnectorAvailable (connectorId: number): Promise<void> {
+ let logged = false
while (!this.chargingStation.isConnectorAvailable(connectorId)) {
if (!logged) {
logger.info(
`${this.logPrefix(
- connectorId,
- )} transaction loop waiting for connector ${connectorId} to be available`,
- );
- logged = true;
+ connectorId
+ )} transaction loop waiting for connector ${connectorId} to be available`
+ )
+ logged = true
}
- await sleep(Constants.CHARGING_STATION_ATG_AVAILABILITY_TIME);
+ await sleep(Constants.CHARGING_STATION_ATG_AVAILABILITY_TIME)
}
}
- private initializeConnectorsStatus(): void {
+ private initializeConnectorsStatus (): void {
if (this.chargingStation.hasEvses) {
for (const [evseId, evseStatus] of this.chargingStation.evses) {
if (evseId > 0) {
for (const connectorId of evseStatus.connectors.keys()) {
- this.connectorsStatus.set(connectorId, this.getConnectorStatus(connectorId));
+ this.connectorsStatus.set(connectorId, this.getConnectorStatus(connectorId))
}
}
}
} else {
for (const connectorId of this.chargingStation.connectors.keys()) {
if (connectorId > 0) {
- this.connectorsStatus.set(connectorId, this.getConnectorStatus(connectorId));
+ this.connectorsStatus.set(connectorId, this.getConnectorStatus(connectorId))
}
}
}
}
- private getConnectorStatus(connectorId: number): Status {
- const connectorStatus = this.chargingStation.getAutomaticTransactionGeneratorStatuses()?.[
- connectorId
- ]
- ? cloneObject<Status>(
- this.chargingStation.getAutomaticTransactionGeneratorStatuses()![connectorId],
+ private getConnectorStatus (connectorId: number): Status {
+ const connectorStatus =
+ this.chargingStation.getAutomaticTransactionGeneratorStatuses()?.[connectorId] != null
+ ? cloneObject<Status>(
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ this.chargingStation.getAutomaticTransactionGeneratorStatuses()![connectorId]
)
- : undefined;
- this.resetConnectorStatus(connectorStatus);
+ : undefined
+ this.resetConnectorStatus(connectorStatus)
return (
connectorStatus ?? {
start: false,
acceptedStopTransactionRequests: 0,
rejectedStopTransactionRequests: 0,
skippedConsecutiveTransactions: 0,
- skippedTransactions: 0,
+ skippedTransactions: 0
}
- );
+ )
}
- private resetConnectorStatus(connectorStatus: Status | undefined): void {
+ private resetConnectorStatus (connectorStatus: Status | undefined): void {
if (connectorStatus === undefined) {
- return;
+ return
}
- delete connectorStatus?.startDate;
- delete connectorStatus?.lastRunDate;
- delete connectorStatus?.stopDate;
- delete connectorStatus?.stoppedDate;
+ delete connectorStatus?.startDate
+ delete connectorStatus?.lastRunDate
+ delete connectorStatus?.stopDate
+ delete connectorStatus?.stoppedDate
if (
!this.started &&
- (connectorStatus.start === true ||
- this.chargingStation.getAutomaticTransactionGeneratorConfiguration().enable === false)
+ (connectorStatus.start ||
+ !this.chargingStation.getAutomaticTransactionGeneratorConfiguration().enable)
) {
- connectorStatus.start = false;
+ connectorStatus.start = false
}
}
- private async startTransaction(
- connectorId: number,
+ private async startTransaction (
+ connectorId: number
): Promise<StartTransactionResponse | undefined> {
- const measureId = 'StartTransaction with ATG';
- const beginId = PerformanceStatistics.beginMeasure(measureId);
- let startResponse: StartTransactionResponse | undefined;
+ const measureId = 'StartTransaction with ATG'
+ const beginId = PerformanceStatistics.beginMeasure(measureId)
+ let startResponse: StartTransactionResponse | undefined
if (this.chargingStation.hasIdTags()) {
const idTag = IdTagsCache.getInstance().getIdTag(
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.chargingStation.getAutomaticTransactionGeneratorConfiguration().idTagDistribution!,
this.chargingStation,
- connectorId,
- );
+ connectorId
+ )
const startTransactionLogMsg = `${this.logPrefix(
- connectorId,
- )} start transaction with an idTag '${idTag}'`;
+ connectorId
+ )} start transaction with an idTag '${idTag}'`
if (this.getRequireAuthorize()) {
- ++this.connectorsStatus.get(connectorId)!.authorizeRequests!;
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ ++this.connectorsStatus.get(connectorId)!.authorizeRequests!
if (await isIdTagAuthorized(this.chargingStation, connectorId, idTag)) {
- ++this.connectorsStatus.get(connectorId)!.acceptedAuthorizeRequests!;
- logger.info(startTransactionLogMsg);
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ ++this.connectorsStatus.get(connectorId)!.acceptedAuthorizeRequests!
+ logger.info(startTransactionLogMsg)
// Start transaction
startResponse = await this.chargingStation.ocppRequestService.requestHandler<
- StartTransactionRequest,
- StartTransactionResponse
+ StartTransactionRequest,
+ StartTransactionResponse
>(this.chargingStation, RequestCommand.START_TRANSACTION, {
connectorId,
- idTag,
- });
- this.handleStartTransactionResponse(connectorId, startResponse);
- PerformanceStatistics.endMeasure(measureId, beginId);
- return startResponse;
+ idTag
+ })
+ this.handleStartTransactionResponse(connectorId, startResponse)
+ PerformanceStatistics.endMeasure(measureId, beginId)
+ return startResponse
}
- ++this.connectorsStatus.get(connectorId)!.rejectedAuthorizeRequests!;
- PerformanceStatistics.endMeasure(measureId, beginId);
- return startResponse;
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ ++this.connectorsStatus.get(connectorId)!.rejectedAuthorizeRequests!
+ PerformanceStatistics.endMeasure(measureId, beginId)
+ return startResponse
}
- logger.info(startTransactionLogMsg);
+ logger.info(startTransactionLogMsg)
// Start transaction
startResponse = await this.chargingStation.ocppRequestService.requestHandler<
- StartTransactionRequest,
- StartTransactionResponse
+ StartTransactionRequest,
+ StartTransactionResponse
>(this.chargingStation, RequestCommand.START_TRANSACTION, {
connectorId,
- idTag,
- });
- this.handleStartTransactionResponse(connectorId, startResponse);
- PerformanceStatistics.endMeasure(measureId, beginId);
- return startResponse;
+ idTag
+ })
+ this.handleStartTransactionResponse(connectorId, startResponse)
+ PerformanceStatistics.endMeasure(measureId, beginId)
+ return startResponse
}
- logger.info(`${this.logPrefix(connectorId)} start transaction without an idTag`);
+ logger.info(`${this.logPrefix(connectorId)} start transaction without an idTag`)
startResponse = await this.chargingStation.ocppRequestService.requestHandler<
- StartTransactionRequest,
- StartTransactionResponse
- >(this.chargingStation, RequestCommand.START_TRANSACTION, { connectorId });
- this.handleStartTransactionResponse(connectorId, startResponse);
- PerformanceStatistics.endMeasure(measureId, beginId);
- return startResponse;
+ StartTransactionRequest,
+ StartTransactionResponse
+ >(this.chargingStation, RequestCommand.START_TRANSACTION, { connectorId })
+ this.handleStartTransactionResponse(connectorId, startResponse)
+ PerformanceStatistics.endMeasure(measureId, beginId)
+ return startResponse
}
- private async stopTransaction(
+ private async stopTransaction (
connectorId: number,
- reason = StopTransactionReason.LOCAL,
+ reason = StopTransactionReason.LOCAL
): Promise<StopTransactionResponse | undefined> {
- const measureId = 'StopTransaction with ATG';
- const beginId = PerformanceStatistics.beginMeasure(measureId);
- let stopResponse: StopTransactionResponse | undefined;
+ const measureId = 'StopTransaction with ATG'
+ const beginId = PerformanceStatistics.beginMeasure(measureId)
+ let stopResponse: StopTransactionResponse | undefined
if (this.chargingStation.getConnectorStatus(connectorId)?.transactionStarted === true) {
logger.info(
`${this.logPrefix(
- connectorId,
+ connectorId
)} stop transaction with id ${this.chargingStation.getConnectorStatus(connectorId)
- ?.transactionId}`,
- );
- stopResponse = await this.chargingStation.stopTransactionOnConnector(connectorId, reason);
- ++this.connectorsStatus.get(connectorId)!.stopTransactionRequests!;
+ ?.transactionId}`
+ )
+ stopResponse = await this.chargingStation.stopTransactionOnConnector(connectorId, reason)
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ ++this.connectorsStatus.get(connectorId)!.stopTransactionRequests!
if (stopResponse?.idTagInfo?.status === AuthorizationStatus.ACCEPTED) {
- ++this.connectorsStatus.get(connectorId)!.acceptedStopTransactionRequests!;
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ ++this.connectorsStatus.get(connectorId)!.acceptedStopTransactionRequests!
} else {
- ++this.connectorsStatus.get(connectorId)!.rejectedStopTransactionRequests!;
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ ++this.connectorsStatus.get(connectorId)!.rejectedStopTransactionRequests!
}
} else {
- const transactionId = this.chargingStation.getConnectorStatus(connectorId)?.transactionId;
+ const transactionId = this.chargingStation.getConnectorStatus(connectorId)?.transactionId
logger.debug(
`${this.logPrefix(connectorId)} stopping a not started transaction${
!isNullOrUndefined(transactionId) ? ` with id ${transactionId}` : ''
- }`,
- );
+ }`
+ )
}
- PerformanceStatistics.endMeasure(measureId, beginId);
- return stopResponse;
+ PerformanceStatistics.endMeasure(measureId, beginId)
+ return stopResponse
}
- private getRequireAuthorize(): boolean {
+ private getRequireAuthorize (): boolean {
return (
this.chargingStation.getAutomaticTransactionGeneratorConfiguration()?.requireAuthorize ?? true
- );
+ )
}
- private logPrefix = (connectorId?: number): string => {
+ private readonly logPrefix = (connectorId?: number): string => {
return logPrefix(
` ${this.chargingStation.stationInfo.chargingStationId} | ATG${
!isNullOrUndefined(connectorId) ? ` on connector #${connectorId}` : ''
- }:`,
- );
- };
+ }:`
+ )
+ }
- private handleStartTransactionResponse(
+ private handleStartTransactionResponse (
connectorId: number,
- startResponse: StartTransactionResponse,
+ startResponse: StartTransactionResponse
): void {
- ++this.connectorsStatus.get(connectorId)!.startTransactionRequests!;
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ ++this.connectorsStatus.get(connectorId)!.startTransactionRequests!
if (startResponse?.idTagInfo?.status === AuthorizationStatus.ACCEPTED) {
- ++this.connectorsStatus.get(connectorId)!.acceptedStartTransactionRequests!;
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ ++this.connectorsStatus.get(connectorId)!.acceptedStartTransactionRequests!
} else {
- logger.warn(`${this.logPrefix(connectorId)} start transaction rejected`);
- ++this.connectorsStatus.get(connectorId)!.rejectedStartTransactionRequests!;
+ logger.warn(`${this.logPrefix(connectorId)} start transaction rejected`)
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ ++this.connectorsStatus.get(connectorId)!.rejectedStartTransactionRequests!
}
}
}
// Partial Copyright Jerome Benoit. 2021-2023. All Rights Reserved.
-import { EventEmitter } from 'node:events';
-import { dirname, extname, join } from 'node:path';
-import process, { exit } from 'node:process';
-import { fileURLToPath } from 'node:url';
+import { EventEmitter } from 'node:events'
+import { dirname, extname, join } from 'node:path'
+import process, { exit } from 'node:process'
+import { fileURLToPath } from 'node:url'
-import chalk from 'chalk';
-import { availableParallelism } from 'poolifier';
+import chalk from 'chalk'
+import { availableParallelism } from 'poolifier'
-import { waitChargingStationEvents } from './Helpers.js';
-import type { AbstractUIServer } from './ui-server/AbstractUIServer.js';
-import { UIServerFactory } from './ui-server/UIServerFactory.js';
-import { version } from '../../package.json';
-import { BaseError } from '../exception/index.js';
-import { type Storage, StorageFactory } from '../performance/index.js';
+import { waitChargingStationEvents } from './Helpers.js'
+import type { AbstractUIServer } from './ui-server/AbstractUIServer.js'
+import { UIServerFactory } from './ui-server/UIServerFactory.js'
+import { version } from '../../package.json'
+import { BaseError } from '../exception/index.js'
+import { type Storage, StorageFactory } from '../performance/index.js'
import {
type ChargingStationData,
type ChargingStationWorkerData,
type Statistics,
type StorageConfiguration,
type UIServerConfiguration,
- type WorkerConfiguration,
-} from '../types/index.js';
+ type WorkerConfiguration
+} from '../types/index.js'
import {
Configuration,
Constants,
isNotEmptyArray,
isNullOrUndefined,
logPrefix,
- logger,
-} from '../utils/index.js';
-import { type WorkerAbstract, WorkerFactory } from '../worker/index.js';
+ logger
+} from '../utils/index.js'
+import { type WorkerAbstract, WorkerFactory } from '../worker/index.js'
-const moduleName = 'Bootstrap';
+const moduleName = 'Bootstrap'
enum exitCodes {
succeeded = 0,
missingChargingStationsConfiguration = 1,
noChargingStationTemplates = 2,
- gracefulShutdownError = 3,
+ gracefulShutdownError = 3
}
export class Bootstrap extends EventEmitter {
- private static instance: Bootstrap | null = null;
- public numberOfChargingStations!: number;
- public numberOfChargingStationTemplates!: number;
- private workerImplementation?: WorkerAbstract<ChargingStationWorkerData>;
- private readonly uiServer?: AbstractUIServer;
- private storage?: Storage;
- private numberOfStartedChargingStations!: number;
- private readonly version: string = version;
- private initializedCounters: boolean;
- private started: boolean;
- private starting: boolean;
- private stopping: boolean;
+ private static instance: Bootstrap | null = null
+ public numberOfChargingStations!: number
+ public numberOfChargingStationTemplates!: number
+ private workerImplementation?: WorkerAbstract<ChargingStationWorkerData>
+ private readonly uiServer?: AbstractUIServer
+ private storage?: Storage
+ private numberOfStartedChargingStations!: number
+ private readonly version: string = version
+ private initializedCounters: boolean
+ private started: boolean
+ private starting: boolean
+ private stopping: boolean
- private constructor() {
- super();
+ private constructor () {
+ super()
for (const signal of ['SIGINT', 'SIGQUIT', 'SIGTERM']) {
- process.on(signal, this.gracefulShutdown.bind(this));
+ process.on(signal, this.gracefulShutdown.bind(this))
}
// Enable unconditionally for now
- handleUnhandledRejection();
- handleUncaughtException();
- this.started = false;
- this.starting = false;
- this.stopping = false;
- this.initializedCounters = false;
- this.initializeCounters();
+ handleUnhandledRejection()
+ handleUncaughtException()
+ this.started = false
+ this.starting = false
+ this.stopping = false
+ this.initializedCounters = false
+ this.initializeCounters()
this.uiServer = UIServerFactory.getUIServerImplementation(
- Configuration.getConfigurationSection<UIServerConfiguration>(ConfigurationSection.uiServer),
- );
- Configuration.configurationChangeCallback = async () => Bootstrap.getInstance().restart(false);
+ Configuration.getConfigurationSection<UIServerConfiguration>(ConfigurationSection.uiServer)
+ )
+ Configuration.configurationChangeCallback = async () => {
+ await Bootstrap.getInstance().restart(false)
+ }
}
- public static getInstance(): Bootstrap {
+ public static getInstance (): Bootstrap {
if (Bootstrap.instance === null) {
- Bootstrap.instance = new Bootstrap();
+ Bootstrap.instance = new Bootstrap()
}
- return Bootstrap.instance;
+ return Bootstrap.instance
}
- public async start(): Promise<void> {
- if (this.started === false) {
- if (this.starting === false) {
- this.starting = true;
- this.on(ChargingStationWorkerMessageEvents.started, this.workerEventStarted);
- this.on(ChargingStationWorkerMessageEvents.stopped, this.workerEventStopped);
- this.on(ChargingStationWorkerMessageEvents.updated, this.workerEventUpdated);
+ public async start (): Promise<void> {
+ if (!this.started) {
+ if (!this.starting) {
+ this.starting = true
+ this.on(ChargingStationWorkerMessageEvents.started, this.workerEventStarted)
+ this.on(ChargingStationWorkerMessageEvents.stopped, this.workerEventStopped)
+ this.on(ChargingStationWorkerMessageEvents.updated, this.workerEventUpdated)
this.on(
ChargingStationWorkerMessageEvents.performanceStatistics,
- this.workerEventPerformanceStatistics,
- );
- this.initializeCounters();
+ this.workerEventPerformanceStatistics
+ )
+ this.initializeCounters()
const workerConfiguration = Configuration.getConfigurationSection<WorkerConfiguration>(
- ConfigurationSection.worker,
- );
- this.initializeWorkerImplementation(workerConfiguration);
- await this.workerImplementation?.start();
+ ConfigurationSection.worker
+ )
+ this.initializeWorkerImplementation(workerConfiguration)
+ await this.workerImplementation?.start()
const performanceStorageConfiguration =
Configuration.getConfigurationSection<StorageConfiguration>(
- ConfigurationSection.performanceStorage,
- );
+ ConfigurationSection.performanceStorage
+ )
if (performanceStorageConfiguration.enabled === true) {
this.storage = StorageFactory.getStorage(
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
performanceStorageConfiguration.type!,
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
performanceStorageConfiguration.uri!,
- this.logPrefix(),
- );
- await this.storage?.open();
+ this.logPrefix()
+ )
+ await this.storage?.open()
}
Configuration.getConfigurationSection<UIServerConfiguration>(ConfigurationSection.uiServer)
- .enabled === true && this.uiServer?.start();
+ .enabled === true && this.uiServer?.start()
// Start ChargingStation object instance in worker thread
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
for (const stationTemplateUrl of Configuration.getStationTemplateUrls()!) {
try {
- const nbStations = stationTemplateUrl.numberOfStations ?? 0;
+ const nbStations = stationTemplateUrl.numberOfStations ?? 0
for (let index = 1; index <= nbStations; index++) {
- await this.startChargingStation(index, stationTemplateUrl);
+ await this.startChargingStation(index, stationTemplateUrl)
}
} catch (error) {
console.error(
chalk.red(
- `Error at starting charging station with template file ${stationTemplateUrl.file}: `,
+ `Error at starting charging station with template file ${stationTemplateUrl.file}: `
),
- error,
- );
+ error
+ )
}
}
console.info(
!isNullOrUndefined(this.workerImplementation?.maxElementsPerWorker)
? ` (${this.workerImplementation?.maxElementsPerWorker} charging station(s) per worker)`
: ''
- }`,
- ),
- );
+ }`
+ )
+ )
Configuration.workerDynamicPoolInUse() &&
console.warn(
chalk.yellow(
- 'Charging stations simulator is using dynamic pool mode. This is an experimental feature with known issues.\nPlease consider using fixed pool or worker set mode instead',
- ),
- );
- console.info(chalk.green('Worker set/pool information:'), this.workerImplementation?.info);
- this.started = true;
- this.starting = false;
+ 'Charging stations simulator is using dynamic pool mode. This is an experimental feature with known issues.\nPlease consider using fixed pool or worker set mode instead'
+ )
+ )
+ console.info(chalk.green('Worker set/pool information:'), this.workerImplementation?.info)
+ this.started = true
+ this.starting = false
} else {
- console.error(chalk.red('Cannot start an already starting charging stations simulator'));
+ console.error(chalk.red('Cannot start an already starting charging stations simulator'))
}
} else {
- console.error(chalk.red('Cannot start an already started charging stations simulator'));
+ console.error(chalk.red('Cannot start an already started charging stations simulator'))
}
}
- public async stop(stopChargingStations = true): Promise<void> {
- if (this.started === true) {
- if (this.stopping === false) {
- this.stopping = true;
- if (stopChargingStations === true) {
+ public async stop (stopChargingStations = true): Promise<void> {
+ if (this.started) {
+ if (!this.stopping) {
+ this.stopping = true
+ if (stopChargingStations) {
await this.uiServer?.sendInternalRequest(
this.uiServer.buildProtocolRequest(
generateUUID(),
ProcedureName.STOP_CHARGING_STATION,
- Constants.EMPTY_FROZEN_OBJECT,
- ),
- );
+ Constants.EMPTY_FROZEN_OBJECT
+ )
+ )
try {
- await this.waitChargingStationsStopped();
+ await this.waitChargingStationsStopped()
} catch (error) {
- console.error(chalk.red('Error while waiting for charging stations to stop: '), error);
+ console.error(chalk.red('Error while waiting for charging stations to stop: '), error)
}
}
- await this.workerImplementation?.stop();
- delete this.workerImplementation;
- this.removeAllListeners();
- await this.storage?.close();
- delete this.storage;
- this.resetCounters();
- this.initializedCounters = false;
- this.started = false;
- this.stopping = false;
+ await this.workerImplementation?.stop()
+ delete this.workerImplementation
+ this.removeAllListeners()
+ await this.storage?.close()
+ delete this.storage
+ this.resetCounters()
+ this.initializedCounters = false
+ this.started = false
+ this.stopping = false
} else {
- console.error(chalk.red('Cannot stop an already stopping charging stations simulator'));
+ console.error(chalk.red('Cannot stop an already stopping charging stations simulator'))
}
} else {
- console.error(chalk.red('Cannot stop an already stopped charging stations simulator'));
+ console.error(chalk.red('Cannot stop an already stopped charging stations simulator'))
}
}
- public async restart(stopChargingStations?: boolean): Promise<void> {
- await this.stop(stopChargingStations);
+ public async restart (stopChargingStations?: boolean): Promise<void> {
+ await this.stop(stopChargingStations)
Configuration.getConfigurationSection<UIServerConfiguration>(ConfigurationSection.uiServer)
- .enabled === false && this.uiServer?.stop();
- await this.start();
+ .enabled === false && this.uiServer?.stop()
+ await this.start()
}
- private async waitChargingStationsStopped(): Promise<string> {
- return new Promise<string>((resolve, reject) => {
+ private async waitChargingStationsStopped (): Promise<string> {
+ return await new Promise<string>((resolve, reject) => {
const waitTimeout = setTimeout(() => {
const message = `Timeout ${formatDurationMilliSeconds(
- Constants.STOP_CHARGING_STATIONS_TIMEOUT,
- )} reached at stopping charging stations`;
- console.warn(chalk.yellow(message));
- reject(new Error(message));
- }, Constants.STOP_CHARGING_STATIONS_TIMEOUT);
+ Constants.STOP_CHARGING_STATIONS_TIMEOUT
+ )} reached at stopping charging stations`
+ console.warn(chalk.yellow(message))
+ reject(new Error(message))
+ }, Constants.STOP_CHARGING_STATIONS_TIMEOUT)
waitChargingStationEvents(
this,
ChargingStationWorkerMessageEvents.stopped,
- this.numberOfChargingStations,
+ this.numberOfChargingStations
)
.then(() => {
- resolve('Charging stations stopped');
+ resolve('Charging stations stopped')
})
.catch(reject)
.finally(() => {
- clearTimeout(waitTimeout);
- });
- });
+ clearTimeout(waitTimeout)
+ })
+ })
}
- private initializeWorkerImplementation(workerConfiguration: WorkerConfiguration): void {
- let elementsPerWorker: number | undefined;
+ private initializeWorkerImplementation (workerConfiguration: WorkerConfiguration): void {
+ let elementsPerWorker: number | undefined
switch (workerConfiguration?.elementsPerWorker) {
case 'auto':
elementsPerWorker =
this.numberOfChargingStations > availableParallelism()
? Math.round(this.numberOfChargingStations / (availableParallelism() * 1.5))
- : 1;
- break;
+ : 1
+ break
case 'all':
- elementsPerWorker = this.numberOfChargingStations;
- break;
+ elementsPerWorker = this.numberOfChargingStations
+ break
}
this.workerImplementation = WorkerFactory.getWorkerImplementation<ChargingStationWorkerData>(
join(
dirname(fileURLToPath(import.meta.url)),
- `ChargingStationWorker${extname(fileURLToPath(import.meta.url))}`,
+ `ChargingStationWorker${extname(fileURLToPath(import.meta.url))}`
),
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
workerConfiguration.processType!,
{
workerStartDelay: workerConfiguration.startDelay,
elementStartDelay: workerConfiguration.elementStartDelay,
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
poolMaxSize: workerConfiguration.poolMaxSize!,
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
poolMinSize: workerConfiguration.poolMinSize!,
elementsPerWorker: elementsPerWorker ?? (workerConfiguration.elementsPerWorker as number),
poolOptions: {
messageHandler: this.messageHandler.bind(this) as (message: unknown) => void,
- workerOptions: { resourceLimits: workerConfiguration.resourceLimits },
- },
- },
- );
+ workerOptions: { resourceLimits: workerConfiguration.resourceLimits }
+ }
+ }
+ )
}
- private messageHandler(
- msg: ChargingStationWorkerMessage<ChargingStationWorkerMessageData>,
+ private messageHandler (
+ msg: ChargingStationWorkerMessage<ChargingStationWorkerMessageData>
): void {
// logger.debug(
// `${this.logPrefix()} ${moduleName}.messageHandler: Worker channel message received: ${JSON.stringify(
// msg,
// undefined,
- // 2,
- // )}`,
- // );
+ // 2
+ // )}`
+ // )
try {
switch (msg.event) {
case ChargingStationWorkerMessageEvents.started:
- this.emit(ChargingStationWorkerMessageEvents.started, msg.data as ChargingStationData);
- break;
+ this.emit(ChargingStationWorkerMessageEvents.started, msg.data as ChargingStationData)
+ break
case ChargingStationWorkerMessageEvents.stopped:
- this.emit(ChargingStationWorkerMessageEvents.stopped, msg.data as ChargingStationData);
- break;
+ this.emit(ChargingStationWorkerMessageEvents.stopped, msg.data as ChargingStationData)
+ break
case ChargingStationWorkerMessageEvents.updated:
- this.emit(ChargingStationWorkerMessageEvents.updated, msg.data as ChargingStationData);
- break;
+ this.emit(ChargingStationWorkerMessageEvents.updated, msg.data as ChargingStationData)
+ break
case ChargingStationWorkerMessageEvents.performanceStatistics:
this.emit(
ChargingStationWorkerMessageEvents.performanceStatistics,
- msg.data as Statistics,
- );
- break;
+ msg.data as Statistics
+ )
+ break
case ChargingStationWorkerMessageEvents.startWorkerElementError:
logger.error(
`${this.logPrefix()} ${moduleName}.messageHandler: Error occured while starting worker element:`,
- msg.data,
- );
- this.emit(ChargingStationWorkerMessageEvents.startWorkerElementError, msg.data);
- break;
+ msg.data
+ )
+ this.emit(ChargingStationWorkerMessageEvents.startWorkerElementError, msg.data)
+ break
case ChargingStationWorkerMessageEvents.startedWorkerElement:
- break;
+ break
default:
throw new BaseError(
`Unknown charging station worker event: '${
msg.event
- }' received with data: ${JSON.stringify(msg.data, undefined, 2)}`,
- );
+ }' received with data: ${JSON.stringify(msg.data, undefined, 2)}`
+ )
}
} catch (error) {
logger.error(
`${this.logPrefix()} ${moduleName}.messageHandler: Error occurred while handling '${
msg.event
}' event:`,
- error,
- );
+ error
+ )
}
}
- private workerEventStarted = (data: ChargingStationData) => {
- this.uiServer?.chargingStations.set(data.stationInfo.hashId, data);
- ++this.numberOfStartedChargingStations;
+ private readonly workerEventStarted = (data: ChargingStationData): void => {
+ this.uiServer?.chargingStations.set(data.stationInfo.hashId, data)
+ ++this.numberOfStartedChargingStations
logger.info(
`${this.logPrefix()} ${moduleName}.workerEventStarted: Charging station ${
data.stationInfo.chargingStationId
} (hashId: ${data.stationInfo.hashId}) started (${
this.numberOfStartedChargingStations
- } started from ${this.numberOfChargingStations})`,
- );
- };
+ } started from ${this.numberOfChargingStations})`
+ )
+ }
- private workerEventStopped = (data: ChargingStationData) => {
- this.uiServer?.chargingStations.set(data.stationInfo.hashId, data);
- --this.numberOfStartedChargingStations;
+ private readonly workerEventStopped = (data: ChargingStationData): void => {
+ this.uiServer?.chargingStations.set(data.stationInfo.hashId, data)
+ --this.numberOfStartedChargingStations
logger.info(
`${this.logPrefix()} ${moduleName}.workerEventStopped: Charging station ${
data.stationInfo.chargingStationId
} (hashId: ${data.stationInfo.hashId}) stopped (${
this.numberOfStartedChargingStations
- } started from ${this.numberOfChargingStations})`,
- );
- };
+ } started from ${this.numberOfChargingStations})`
+ )
+ }
- private workerEventUpdated = (data: ChargingStationData) => {
- this.uiServer?.chargingStations.set(data.stationInfo.hashId, data);
- };
+ private readonly workerEventUpdated = (data: ChargingStationData): void => {
+ this.uiServer?.chargingStations.set(data.stationInfo.hashId, data)
+ }
- private workerEventPerformanceStatistics = (data: Statistics) => {
- this.storage?.storePerformanceStatistics(data) as void;
- };
+ private readonly workerEventPerformanceStatistics = (data: Statistics): void => {
+ this.storage?.storePerformanceStatistics(data) as undefined
+ }
- private initializeCounters() {
- if (this.initializedCounters === false) {
- this.resetCounters();
- const stationTemplateUrls = Configuration.getStationTemplateUrls()!;
+ private initializeCounters (): void {
+ if (!this.initializedCounters) {
+ this.resetCounters()
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ const stationTemplateUrls = Configuration.getStationTemplateUrls()!
if (isNotEmptyArray(stationTemplateUrls)) {
- this.numberOfChargingStationTemplates = stationTemplateUrls.length;
+ this.numberOfChargingStationTemplates = stationTemplateUrls.length
for (const stationTemplateUrl of stationTemplateUrls) {
- this.numberOfChargingStations += stationTemplateUrl.numberOfStations ?? 0;
+ this.numberOfChargingStations += stationTemplateUrl.numberOfStations ?? 0
}
} else {
console.warn(
- chalk.yellow("'stationTemplateUrls' not defined or empty in configuration, exiting"),
- );
- exit(exitCodes.missingChargingStationsConfiguration);
+ chalk.yellow("'stationTemplateUrls' not defined or empty in configuration, exiting")
+ )
+ exit(exitCodes.missingChargingStationsConfiguration)
}
if (this.numberOfChargingStations === 0) {
- console.warn(
- chalk.yellow('No charging station template enabled in configuration, exiting'),
- );
- exit(exitCodes.noChargingStationTemplates);
+ console.warn(chalk.yellow('No charging station template enabled in configuration, exiting'))
+ exit(exitCodes.noChargingStationTemplates)
}
- this.initializedCounters = true;
+ this.initializedCounters = true
}
}
- private resetCounters(): void {
- this.numberOfChargingStationTemplates = 0;
- this.numberOfChargingStations = 0;
- this.numberOfStartedChargingStations = 0;
+ private resetCounters (): void {
+ this.numberOfChargingStationTemplates = 0
+ this.numberOfChargingStations = 0
+ this.numberOfStartedChargingStations = 0
}
- private async startChargingStation(
+ private async startChargingStation (
index: number,
- stationTemplateUrl: StationTemplateUrl,
+ stationTemplateUrl: StationTemplateUrl
): Promise<void> {
await this.workerImplementation?.addElement({
index,
dirname(fileURLToPath(import.meta.url)),
'assets',
'station-templates',
- stationTemplateUrl.file,
- ),
- });
+ stationTemplateUrl.file
+ )
+ })
}
- private gracefulShutdown(): void {
+ private gracefulShutdown (): void {
this.stop()
.then(() => {
- console.info(`${chalk.green('Graceful shutdown')}`);
- this.uiServer?.stop();
+ console.info(`${chalk.green('Graceful shutdown')}`)
+ this.uiServer?.stop()
// stop() asks for charging stations to stop by default
this.waitChargingStationsStopped()
.then(() => {
- exit(exitCodes.succeeded);
+ exit(exitCodes.succeeded)
})
.catch(() => {
- exit(exitCodes.gracefulShutdownError);
- });
+ exit(exitCodes.gracefulShutdownError)
+ })
})
.catch((error) => {
- console.error(chalk.red('Error while shutdowning charging stations simulator: '), error);
- exit(exitCodes.gracefulShutdownError);
- });
+ console.error(chalk.red('Error while shutdowning charging stations simulator: '), error)
+ exit(exitCodes.gracefulShutdownError)
+ })
}
- private logPrefix = (): string => {
- return logPrefix(' Bootstrap |');
- };
+ private readonly logPrefix = (): string => {
+ return logPrefix(' Bootstrap |')
+ }
}
// Partial Copyright Jerome Benoit. 2021-2023. All Rights Reserved.
-import { createHash } from 'node:crypto';
-import { EventEmitter } from 'node:events';
-import { type FSWatcher, existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
-import { dirname, join } from 'node:path';
-import { URL } from 'node:url';
-import { parentPort } from 'node:worker_threads';
-
-import { millisecondsToSeconds, secondsToMilliseconds } from 'date-fns';
-import merge from 'just-merge';
-import { type RawData, WebSocket } from 'ws';
-
-import { AutomaticTransactionGenerator } from './AutomaticTransactionGenerator.js';
-import { ChargingStationWorkerBroadcastChannel } from './broadcast-channel/ChargingStationWorkerBroadcastChannel.js';
+import { createHash } from 'node:crypto'
+import { EventEmitter } from 'node:events'
+import { type FSWatcher, existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'
+import { dirname, join } from 'node:path'
+import { URL } from 'node:url'
+import { parentPort } from 'node:worker_threads'
+
+import { millisecondsToSeconds, secondsToMilliseconds } from 'date-fns'
+import merge from 'just-merge'
+import { type RawData, WebSocket } from 'ws'
+
+import { AutomaticTransactionGenerator } from './AutomaticTransactionGenerator.js'
+import { ChargingStationWorkerBroadcastChannel } from './broadcast-channel/ChargingStationWorkerBroadcastChannel.js'
import {
addConfigurationKey,
deleteConfigurationKey,
getConfigurationKey,
- setConfigurationKeyValue,
-} from './ConfigurationKeyUtils.js';
+ setConfigurationKeyValue
+} from './ConfigurationKeyUtils.js'
import {
buildConnectorsMap,
checkChargingStation,
initializeConnectorsMapStatus,
propagateSerialNumber,
stationTemplateToStationInfo,
- warnTemplateKeysDeprecation,
-} from './Helpers.js';
-import { IdTagsCache } from './IdTagsCache.js';
+ warnTemplateKeysDeprecation
+} from './Helpers.js'
+import { IdTagsCache } from './IdTagsCache.js'
import {
OCPP16IncomingRequestService,
OCPP16RequestService,
buildStatusNotificationRequest,
buildTransactionEndMeterValue,
getMessageTypeString,
- sendAndSetConnectorStatus,
-} from './ocpp/index.js';
-import { SharedLRUCache } from './SharedLRUCache.js';
-import { BaseError, OCPPError } from '../exception/index.js';
-import { PerformanceStatistics } from '../performance/index.js';
+ sendAndSetConnectorStatus
+} from './ocpp/index.js'
+import { SharedLRUCache } from './SharedLRUCache.js'
+import { BaseError, OCPPError } from '../exception/index.js'
+import { PerformanceStatistics } from '../performance/index.js'
import {
type AutomaticTransactionGeneratorConfiguration,
AvailabilityType,
type Status,
type StatusNotificationRequest,
type StatusNotificationResponse,
- StopTransactionReason,
+ type StopTransactionReason,
type StopTransactionRequest,
type StopTransactionResponse,
SupervisionUrlDistribution,
SupportedFeatureProfiles,
- Voltage,
+ type Voltage,
type WSError,
WebSocketCloseEventStatusCode,
- type WsOptions,
-} from '../types/index.js';
+ type WsOptions
+} from '../types/index.js'
import {
ACElectricUtils,
AsyncLock,
roundTo,
secureRandom,
sleep,
- watchJsonFile,
-} from '../utils/index.js';
+ watchJsonFile
+} from '../utils/index.js'
export class ChargingStation extends EventEmitter {
- public readonly index: number;
- public readonly templateFile: string;
- public stationInfo!: ChargingStationInfo;
- public started: boolean;
- public starting: boolean;
- public idTagsCache: IdTagsCache;
- public automaticTransactionGenerator!: AutomaticTransactionGenerator | undefined;
- public ocppConfiguration!: ChargingStationOcppConfiguration | undefined;
- public wsConnection: WebSocket | null;
- public readonly connectors: Map<number, ConnectorStatus>;
- public readonly evses: Map<number, EvseStatus>;
- public readonly requests: Map<string, CachedRequest>;
- public performanceStatistics!: PerformanceStatistics | undefined;
- public heartbeatSetInterval?: NodeJS.Timeout;
- public ocppRequestService!: OCPPRequestService;
- public bootNotificationRequest!: BootNotificationRequest;
- public bootNotificationResponse!: BootNotificationResponse | undefined;
- public powerDivider!: number;
- private stopping: boolean;
- private configurationFile!: string;
- private configurationFileHash!: string;
- private connectorsConfigurationHash!: string;
- private evsesConfigurationHash!: string;
- private automaticTransactionGeneratorConfiguration?: AutomaticTransactionGeneratorConfiguration;
- private ocppIncomingRequestService!: OCPPIncomingRequestService;
- private readonly messageBuffer: Set<string>;
- private configuredSupervisionUrl!: URL;
- private autoReconnectRetryCount: number;
- private templateFileWatcher!: FSWatcher | undefined;
- private templateFileHash!: string;
- private readonly sharedLRUCache: SharedLRUCache;
- private webSocketPingSetInterval?: NodeJS.Timeout;
- private readonly chargingStationWorkerBroadcastChannel: ChargingStationWorkerBroadcastChannel;
- private flushMessageBufferSetInterval?: NodeJS.Timeout;
-
- constructor(index: number, templateFile: string) {
- super();
- this.started = false;
- this.starting = false;
- this.stopping = false;
- this.wsConnection = null;
- this.autoReconnectRetryCount = 0;
- this.index = index;
- this.templateFile = templateFile;
- this.connectors = new Map<number, ConnectorStatus>();
- this.evses = new Map<number, EvseStatus>();
- this.requests = new Map<string, CachedRequest>();
- this.messageBuffer = new Set<string>();
- this.sharedLRUCache = SharedLRUCache.getInstance();
- this.idTagsCache = IdTagsCache.getInstance();
- this.chargingStationWorkerBroadcastChannel = new ChargingStationWorkerBroadcastChannel(this);
+ public readonly index: number
+ public readonly templateFile: string
+ public stationInfo!: ChargingStationInfo
+ public started: boolean
+ public starting: boolean
+ public idTagsCache: IdTagsCache
+ public automaticTransactionGenerator!: AutomaticTransactionGenerator | undefined
+ public ocppConfiguration!: ChargingStationOcppConfiguration | undefined
+ public wsConnection: WebSocket | null
+ public readonly connectors: Map<number, ConnectorStatus>
+ public readonly evses: Map<number, EvseStatus>
+ public readonly requests: Map<string, CachedRequest>
+ public performanceStatistics!: PerformanceStatistics | undefined
+ public heartbeatSetInterval?: NodeJS.Timeout
+ public ocppRequestService!: OCPPRequestService
+ public bootNotificationRequest!: BootNotificationRequest
+ public bootNotificationResponse!: BootNotificationResponse | undefined
+ public powerDivider!: number
+ private stopping: boolean
+ private configurationFile!: string
+ private configurationFileHash!: string
+ private connectorsConfigurationHash!: string
+ private evsesConfigurationHash!: string
+ private automaticTransactionGeneratorConfiguration?: AutomaticTransactionGeneratorConfiguration
+ private ocppIncomingRequestService!: OCPPIncomingRequestService
+ private readonly messageBuffer: Set<string>
+ private configuredSupervisionUrl!: URL
+ private autoReconnectRetryCount: number
+ private templateFileWatcher!: FSWatcher | undefined
+ private templateFileHash!: string
+ private readonly sharedLRUCache: SharedLRUCache
+ private webSocketPingSetInterval?: NodeJS.Timeout
+ private readonly chargingStationWorkerBroadcastChannel: ChargingStationWorkerBroadcastChannel
+ private flushMessageBufferSetInterval?: NodeJS.Timeout
+
+ constructor (index: number, templateFile: string) {
+ super()
+ this.started = false
+ this.starting = false
+ this.stopping = false
+ this.wsConnection = null
+ this.autoReconnectRetryCount = 0
+ this.index = index
+ this.templateFile = templateFile
+ this.connectors = new Map<number, ConnectorStatus>()
+ this.evses = new Map<number, EvseStatus>()
+ this.requests = new Map<string, CachedRequest>()
+ this.messageBuffer = new Set<string>()
+ this.sharedLRUCache = SharedLRUCache.getInstance()
+ this.idTagsCache = IdTagsCache.getInstance()
+ this.chargingStationWorkerBroadcastChannel = new ChargingStationWorkerBroadcastChannel(this)
this.on(ChargingStationEvents.started, () => {
- parentPort?.postMessage(buildStartedMessage(this));
- });
+ parentPort?.postMessage(buildStartedMessage(this))
+ })
this.on(ChargingStationEvents.stopped, () => {
- parentPort?.postMessage(buildStoppedMessage(this));
- });
+ parentPort?.postMessage(buildStoppedMessage(this))
+ })
this.on(ChargingStationEvents.updated, () => {
- parentPort?.postMessage(buildUpdatedMessage(this));
- });
+ parentPort?.postMessage(buildUpdatedMessage(this))
+ })
- this.initialize();
+ this.initialize()
}
- public get hasEvses(): boolean {
- return this.connectors.size === 0 && this.evses.size > 0;
+ public get hasEvses (): boolean {
+ return this.connectors.size === 0 && this.evses.size > 0
}
- private get wsConnectionUrl(): URL {
+ private get wsConnectionUrl (): URL {
return new URL(
`${
this.stationInfo?.supervisionUrlOcppConfiguration === true &&
isNotEmptyString(this.stationInfo?.supervisionUrlOcppKey) &&
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
isNotEmptyString(getConfigurationKey(this, this.stationInfo.supervisionUrlOcppKey!)?.value)
- ? getConfigurationKey(this, this.stationInfo.supervisionUrlOcppKey!)!.value
+ ? // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ getConfigurationKey(this, this.stationInfo.supervisionUrlOcppKey!)!.value
: this.configuredSupervisionUrl.href
- }/${this.stationInfo.chargingStationId}`,
- );
+ }/${this.stationInfo.chargingStationId}`
+ )
}
public logPrefix = (): string => {
if (isNotEmptyString(this?.stationInfo?.chargingStationId)) {
- return logPrefix(` ${this?.stationInfo?.chargingStationId} |`);
+ return logPrefix(` ${this?.stationInfo?.chargingStationId} |`)
}
- let stationTemplate: ChargingStationTemplate | undefined;
+ let stationTemplate: ChargingStationTemplate | undefined
try {
stationTemplate = JSON.parse(
- readFileSync(this.templateFile, 'utf8'),
- ) as ChargingStationTemplate;
+ readFileSync(this.templateFile, 'utf8')
+ ) as ChargingStationTemplate
} catch {
- stationTemplate = undefined;
+ stationTemplate = undefined
}
- return logPrefix(` ${getChargingStationId(this.index, stationTemplate)} |`);
- };
+ return logPrefix(` ${getChargingStationId(this.index, stationTemplate)} |`)
+ }
- public hasIdTags(): boolean {
- return isNotEmptyArray(this.idTagsCache.getIdTags(getIdTagsFile(this.stationInfo)!));
+ public hasIdTags (): boolean {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ return isNotEmptyArray(this.idTagsCache.getIdTags(getIdTagsFile(this.stationInfo)!))
}
- public getNumberOfPhases(stationInfo?: ChargingStationInfo): number {
- const localStationInfo: ChargingStationInfo = stationInfo ?? this.stationInfo;
+ public getNumberOfPhases (stationInfo?: ChargingStationInfo): number {
+ const localStationInfo: ChargingStationInfo = stationInfo ?? this.stationInfo
switch (this.getCurrentOutType(stationInfo)) {
case CurrentType.AC:
- return localStationInfo.numberOfPhases ?? 3;
+ return localStationInfo.numberOfPhases ?? 3
case CurrentType.DC:
- return 0;
+ return 0
}
}
- public isWebSocketConnectionOpened(): boolean {
- return this?.wsConnection?.readyState === WebSocket.OPEN;
+ public isWebSocketConnectionOpened (): boolean {
+ return this?.wsConnection?.readyState === WebSocket.OPEN
}
- public inUnknownState(): boolean {
- return isNullOrUndefined(this?.bootNotificationResponse?.status);
+ public inUnknownState (): boolean {
+ return isNullOrUndefined(this?.bootNotificationResponse?.status)
}
- public inPendingState(): boolean {
- return this?.bootNotificationResponse?.status === RegistrationStatusEnumType.PENDING;
+ public inPendingState (): boolean {
+ return this?.bootNotificationResponse?.status === RegistrationStatusEnumType.PENDING
}
- public inAcceptedState(): boolean {
- return this?.bootNotificationResponse?.status === RegistrationStatusEnumType.ACCEPTED;
+ public inAcceptedState (): boolean {
+ return this?.bootNotificationResponse?.status === RegistrationStatusEnumType.ACCEPTED
}
- public inRejectedState(): boolean {
- return this?.bootNotificationResponse?.status === RegistrationStatusEnumType.REJECTED;
+ public inRejectedState (): boolean {
+ return this?.bootNotificationResponse?.status === RegistrationStatusEnumType.REJECTED
}
- public isRegistered(): boolean {
- return (
- this.inUnknownState() === false &&
- (this.inAcceptedState() === true || this.inPendingState() === true)
- );
+ public isRegistered (): boolean {
+ return !this.inUnknownState() && (this.inAcceptedState() || this.inPendingState())
}
- public isChargingStationAvailable(): boolean {
- return this.getConnectorStatus(0)?.availability === AvailabilityType.Operative;
+ public isChargingStationAvailable (): boolean {
+ return this.getConnectorStatus(0)?.availability === AvailabilityType.Operative
}
- public hasConnector(connectorId: number): boolean {
+ public hasConnector (connectorId: number): boolean {
if (this.hasEvses) {
for (const evseStatus of this.evses.values()) {
if (evseStatus.connectors.has(connectorId)) {
- return true;
+ return true
}
}
- return false;
+ return false
}
- return this.connectors.has(connectorId);
+ return this.connectors.has(connectorId)
}
- public isConnectorAvailable(connectorId: number): boolean {
+ public isConnectorAvailable (connectorId: number): boolean {
return (
connectorId > 0 &&
this.getConnectorStatus(connectorId)?.availability === AvailabilityType.Operative
- );
+ )
}
- public getNumberOfConnectors(): number {
+ public getNumberOfConnectors (): number {
if (this.hasEvses) {
- let numberOfConnectors = 0;
+ let numberOfConnectors = 0
for (const [evseId, evseStatus] of this.evses) {
if (evseId > 0) {
- numberOfConnectors += evseStatus.connectors.size;
+ numberOfConnectors += evseStatus.connectors.size
}
}
- return numberOfConnectors;
+ return numberOfConnectors
}
- return this.connectors.has(0) ? this.connectors.size - 1 : this.connectors.size;
+ return this.connectors.has(0) ? this.connectors.size - 1 : this.connectors.size
}
- public getNumberOfEvses(): number {
- return this.evses.has(0) ? this.evses.size - 1 : this.evses.size;
+ public getNumberOfEvses (): number {
+ return this.evses.has(0) ? this.evses.size - 1 : this.evses.size
}
- public getConnectorStatus(connectorId: number): ConnectorStatus | undefined {
+ public getConnectorStatus (connectorId: number): ConnectorStatus | undefined {
if (this.hasEvses) {
for (const evseStatus of this.evses.values()) {
if (evseStatus.connectors.has(connectorId)) {
- return evseStatus.connectors.get(connectorId);
+ return evseStatus.connectors.get(connectorId)
}
}
- return undefined;
+ return undefined
}
- return this.connectors.get(connectorId);
+ return this.connectors.get(connectorId)
}
- public getConnectorMaximumAvailablePower(connectorId: number): number {
- let connectorAmperageLimitationPowerLimit: number | undefined;
+ public getConnectorMaximumAvailablePower (connectorId: number): number {
+ let connectorAmperageLimitationPowerLimit: number | undefined
if (
!isNullOrUndefined(this.getAmperageLimitation()) &&
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.getAmperageLimitation()! < this.stationInfo.maximumAmperage!
) {
connectorAmperageLimitationPowerLimit =
(this.stationInfo?.currentOutType === CurrentType.AC
? ACElectricUtils.powerTotal(
- this.getNumberOfPhases(),
- this.stationInfo.voltageOut!,
- this.getAmperageLimitation()! *
- (this.hasEvses ? this.getNumberOfEvses() : this.getNumberOfConnectors()),
- )
- : DCElectricUtils.power(this.stationInfo.voltageOut!, this.getAmperageLimitation()!)) /
- this.powerDivider;
+ this.getNumberOfPhases(),
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ this.stationInfo.voltageOut!,
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ this.getAmperageLimitation()! *
+ (this.hasEvses ? this.getNumberOfEvses() : this.getNumberOfConnectors())
+ )
+ : // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ DCElectricUtils.power(this.stationInfo.voltageOut!, this.getAmperageLimitation()!)) /
+ this.powerDivider
}
- const connectorMaximumPower = this.stationInfo.maximumPower! / this.powerDivider;
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ const connectorMaximumPower = this.stationInfo.maximumPower! / this.powerDivider
const connectorChargingProfilesPowerLimit =
- getChargingStationConnectorChargingProfilesPowerLimit(this, connectorId);
+ getChargingStationConnectorChargingProfilesPowerLimit(this, connectorId)
return min(
isNaN(connectorMaximumPower) ? Infinity : connectorMaximumPower,
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
isNaN(connectorAmperageLimitationPowerLimit!)
? Infinity
- : connectorAmperageLimitationPowerLimit!,
- isNaN(connectorChargingProfilesPowerLimit!) ? Infinity : connectorChargingProfilesPowerLimit!,
- );
+ : // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ connectorAmperageLimitationPowerLimit!,
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ isNaN(connectorChargingProfilesPowerLimit!) ? Infinity : connectorChargingProfilesPowerLimit!
+ )
}
- public getTransactionIdTag(transactionId: number): string | undefined {
+ public getTransactionIdTag (transactionId: number): string | undefined {
if (this.hasEvses) {
for (const evseStatus of this.evses.values()) {
for (const connectorStatus of evseStatus.connectors.values()) {
if (connectorStatus.transactionId === transactionId) {
- return connectorStatus.transactionIdTag;
+ return connectorStatus.transactionIdTag
}
}
}
} else {
for (const connectorId of this.connectors.keys()) {
if (this.getConnectorStatus(connectorId)?.transactionId === transactionId) {
- return this.getConnectorStatus(connectorId)?.transactionIdTag;
+ return this.getConnectorStatus(connectorId)?.transactionIdTag
}
}
}
}
- public getNumberOfRunningTransactions(): number {
- let numberOfRunningTransactions = 0;
+ public getNumberOfRunningTransactions (): number {
+ let numberOfRunningTransactions = 0
if (this.hasEvses) {
for (const [evseId, evseStatus] of this.evses) {
if (evseId === 0) {
- continue;
+ continue
}
for (const connectorStatus of evseStatus.connectors.values()) {
if (connectorStatus.transactionStarted === true) {
- ++numberOfRunningTransactions;
+ ++numberOfRunningTransactions
}
}
}
} else {
for (const connectorId of this.connectors.keys()) {
if (connectorId > 0 && this.getConnectorStatus(connectorId)?.transactionStarted === true) {
- ++numberOfRunningTransactions;
+ ++numberOfRunningTransactions
}
}
}
- return numberOfRunningTransactions;
+ return numberOfRunningTransactions
}
- public getConnectorIdByTransactionId(transactionId: number): number | undefined {
+ public getConnectorIdByTransactionId (transactionId: number): number | undefined {
if (this.hasEvses) {
for (const evseStatus of this.evses.values()) {
for (const [connectorId, connectorStatus] of evseStatus.connectors) {
if (connectorStatus.transactionId === transactionId) {
- return connectorId;
+ return connectorId
}
}
}
} else {
for (const connectorId of this.connectors.keys()) {
if (this.getConnectorStatus(connectorId)?.transactionId === transactionId) {
- return connectorId;
+ return connectorId
}
}
}
}
- public getEnergyActiveImportRegisterByTransactionId(
+ public getEnergyActiveImportRegisterByTransactionId (
transactionId: number,
- rounded = false,
+ rounded = false
): number {
return this.getEnergyActiveImportRegister(
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.getConnectorStatus(this.getConnectorIdByTransactionId(transactionId)!)!,
- rounded,
- );
+ rounded
+ )
}
- public getEnergyActiveImportRegisterByConnectorId(connectorId: number, rounded = false): number {
- return this.getEnergyActiveImportRegister(this.getConnectorStatus(connectorId)!, rounded);
+ public getEnergyActiveImportRegisterByConnectorId (connectorId: number, rounded = false): number {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ return this.getEnergyActiveImportRegister(this.getConnectorStatus(connectorId)!, rounded)
}
- public getAuthorizeRemoteTxRequests(): boolean {
+ public getAuthorizeRemoteTxRequests (): boolean {
const authorizeRemoteTxRequests = getConfigurationKey(
this,
- StandardParametersKey.AuthorizeRemoteTxRequests,
- );
+ StandardParametersKey.AuthorizeRemoteTxRequests
+ )
return authorizeRemoteTxRequests !== undefined
? convertToBoolean(authorizeRemoteTxRequests.value)
- : false;
+ : false
}
- public getLocalAuthListEnabled(): boolean {
+ public getLocalAuthListEnabled (): boolean {
const localAuthListEnabled = getConfigurationKey(
this,
- StandardParametersKey.LocalAuthListEnabled,
- );
- return localAuthListEnabled !== undefined
- ? convertToBoolean(localAuthListEnabled.value)
- : false;
+ StandardParametersKey.LocalAuthListEnabled
+ )
+ return localAuthListEnabled !== undefined ? convertToBoolean(localAuthListEnabled.value) : false
}
- public getHeartbeatInterval(): number {
- const HeartbeatInterval = getConfigurationKey(this, StandardParametersKey.HeartbeatInterval);
+ public getHeartbeatInterval (): number {
+ const HeartbeatInterval = getConfigurationKey(this, StandardParametersKey.HeartbeatInterval)
if (HeartbeatInterval !== undefined) {
- return secondsToMilliseconds(convertToInt(HeartbeatInterval.value));
+ return secondsToMilliseconds(convertToInt(HeartbeatInterval.value))
}
- const HeartBeatInterval = getConfigurationKey(this, StandardParametersKey.HeartBeatInterval);
+ const HeartBeatInterval = getConfigurationKey(this, StandardParametersKey.HeartBeatInterval)
if (HeartBeatInterval !== undefined) {
- return secondsToMilliseconds(convertToInt(HeartBeatInterval.value));
+ return secondsToMilliseconds(convertToInt(HeartBeatInterval.value))
}
this.stationInfo?.autoRegister === false &&
logger.warn(
`${this.logPrefix()} Heartbeat interval configuration key not set, using default value: ${
Constants.DEFAULT_HEARTBEAT_INTERVAL
- }`,
- );
- return Constants.DEFAULT_HEARTBEAT_INTERVAL;
+ }`
+ )
+ return Constants.DEFAULT_HEARTBEAT_INTERVAL
}
- public setSupervisionUrl(url: string): void {
+ public setSupervisionUrl (url: string): void {
if (
this.stationInfo?.supervisionUrlOcppConfiguration === true &&
isNotEmptyString(this.stationInfo?.supervisionUrlOcppKey)
) {
- setConfigurationKeyValue(this, this.stationInfo.supervisionUrlOcppKey!, url);
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ setConfigurationKeyValue(this, this.stationInfo.supervisionUrlOcppKey!, url)
} else {
- this.stationInfo.supervisionUrls = url;
- this.saveStationInfo();
- this.configuredSupervisionUrl = this.getConfiguredSupervisionUrl();
+ this.stationInfo.supervisionUrls = url
+ this.saveStationInfo()
+ this.configuredSupervisionUrl = this.getConfiguredSupervisionUrl()
}
}
- public startHeartbeat(): void {
+ public startHeartbeat (): void {
if (this.getHeartbeatInterval() > 0 && this.heartbeatSetInterval === undefined) {
this.heartbeatSetInterval = setInterval(() => {
this.ocppRequestService
.catch((error) => {
logger.error(
`${this.logPrefix()} Error while sending '${RequestCommand.HEARTBEAT}':`,
- error,
- );
- });
- }, this.getHeartbeatInterval());
+ error
+ )
+ })
+ }, this.getHeartbeatInterval())
logger.info(
`${this.logPrefix()} Heartbeat started every ${formatDurationMilliSeconds(
- this.getHeartbeatInterval(),
- )}`,
- );
+ this.getHeartbeatInterval()
+ )}`
+ )
} else if (this.heartbeatSetInterval !== undefined) {
logger.info(
`${this.logPrefix()} Heartbeat already started every ${formatDurationMilliSeconds(
- this.getHeartbeatInterval(),
- )}`,
- );
+ this.getHeartbeatInterval()
+ )}`
+ )
} else {
logger.error(
- `${this.logPrefix()} Heartbeat interval set to ${this.getHeartbeatInterval()}, not starting the heartbeat`,
- );
+ `${this.logPrefix()} Heartbeat interval set to ${this.getHeartbeatInterval()}, not starting the heartbeat`
+ )
}
}
- public restartHeartbeat(): void {
+ public restartHeartbeat (): void {
// Stop heartbeat
- this.stopHeartbeat();
+ this.stopHeartbeat()
// Start heartbeat
- this.startHeartbeat();
+ this.startHeartbeat()
}
- public restartWebSocketPing(): void {
+ public restartWebSocketPing (): void {
// Stop WebSocket ping
- this.stopWebSocketPing();
+ this.stopWebSocketPing()
// Start WebSocket ping
- this.startWebSocketPing();
+ this.startWebSocketPing()
}
- public startMeterValues(connectorId: number, interval: number): void {
+ public startMeterValues (connectorId: number, interval: number): void {
if (connectorId === 0) {
- logger.error(
- `${this.logPrefix()} Trying to start MeterValues on connector id ${connectorId}`,
- );
- return;
+ logger.error(`${this.logPrefix()} Trying to start MeterValues on connector id ${connectorId}`)
+ return
}
- if (!this.getConnectorStatus(connectorId)) {
+ if (this.getConnectorStatus(connectorId) == null) {
logger.error(
`${this.logPrefix()} Trying to start MeterValues on non existing connector id
- ${connectorId}`,
- );
- return;
+ ${connectorId}`
+ )
+ return
}
if (this.getConnectorStatus(connectorId)?.transactionStarted === false) {
logger.error(
- `${this.logPrefix()} Trying to start MeterValues on connector id ${connectorId} with no transaction started`,
- );
- return;
+ `${this.logPrefix()} Trying to start MeterValues on connector id ${connectorId} with no transaction started`
+ )
+ return
} else if (
this.getConnectorStatus(connectorId)?.transactionStarted === true &&
isNullOrUndefined(this.getConnectorStatus(connectorId)?.transactionId)
) {
logger.error(
- `${this.logPrefix()} Trying to start MeterValues on connector id ${connectorId} with no transaction id`,
- );
- return;
+ `${this.logPrefix()} Trying to start MeterValues on connector id ${connectorId} with no transaction id`
+ )
+ return
}
if (interval > 0) {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.getConnectorStatus(connectorId)!.transactionSetInterval = setInterval(() => {
const meterValue = buildMeterValue(
this,
connectorId,
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.getConnectorStatus(connectorId)!.transactionId!,
- interval,
- );
+ interval
+ )
this.ocppRequestService
.requestHandler<MeterValuesRequest, MeterValuesResponse>(
- this,
- RequestCommand.METER_VALUES,
- {
- connectorId,
- transactionId: this.getConnectorStatus(connectorId)?.transactionId,
- meterValue: [meterValue],
- },
- )
+ this,
+ RequestCommand.METER_VALUES,
+ {
+ connectorId,
+ transactionId: this.getConnectorStatus(connectorId)?.transactionId,
+ meterValue: [meterValue]
+ }
+ )
.catch((error) => {
logger.error(
`${this.logPrefix()} Error while sending '${RequestCommand.METER_VALUES}':`,
- error,
- );
- });
- }, interval);
+ error
+ )
+ })
+ }, interval)
} else {
logger.error(
`${this.logPrefix()} Charging station ${
StandardParametersKey.MeterValueSampleInterval
- } configuration set to ${interval}, not sending MeterValues`,
- );
+ } configuration set to ${interval}, not sending MeterValues`
+ )
}
}
- public stopMeterValues(connectorId: number) {
+ public stopMeterValues (connectorId: number): void {
if (this.getConnectorStatus(connectorId)?.transactionSetInterval !== undefined) {
- clearInterval(this.getConnectorStatus(connectorId)?.transactionSetInterval);
+ clearInterval(this.getConnectorStatus(connectorId)?.transactionSetInterval)
}
}
- public start(): void {
- if (this.started === false) {
- if (this.starting === false) {
- this.starting = true;
+ public start (): void {
+ if (!this.started) {
+ if (!this.starting) {
+ this.starting = true
if (this.stationInfo?.enableStatistics === true) {
- this.performanceStatistics?.start();
+ this.performanceStatistics?.start()
}
- this.openWSConnection();
+ this.openWSConnection()
// Monitor charging station template file
this.templateFileWatcher = watchJsonFile(
this.templateFile,
logger.debug(
`${this.logPrefix()} ${FileType.ChargingStationTemplate} ${
this.templateFile
- } file have changed, reload`,
- );
- this.sharedLRUCache.deleteChargingStationTemplate(this.templateFileHash);
+ } file have changed, reload`
+ )
+ this.sharedLRUCache.deleteChargingStationTemplate(this.templateFileHash)
// Initialize
- this.initialize();
- this.idTagsCache.deleteIdTags(getIdTagsFile(this.stationInfo)!);
+ this.initialize()
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ this.idTagsCache.deleteIdTags(getIdTagsFile(this.stationInfo)!)
// Restart the ATG
- this.stopAutomaticTransactionGenerator();
- delete this.automaticTransactionGeneratorConfiguration;
- if (this.getAutomaticTransactionGeneratorConfiguration().enable === true) {
- this.startAutomaticTransactionGenerator();
+ this.stopAutomaticTransactionGenerator()
+ delete this.automaticTransactionGeneratorConfiguration
+ if (this.getAutomaticTransactionGeneratorConfiguration().enable) {
+ this.startAutomaticTransactionGenerator()
}
if (this.stationInfo?.enableStatistics === true) {
- this.performanceStatistics?.restart();
+ this.performanceStatistics?.restart()
} else {
- this.performanceStatistics?.stop();
+ this.performanceStatistics?.stop()
}
// FIXME?: restart heartbeat and WebSocket ping when their interval values have changed
} catch (error) {
logger.error(
`${this.logPrefix()} ${FileType.ChargingStationTemplate} file monitoring error:`,
- error,
- );
+ error
+ )
}
}
- },
- );
- this.started = true;
- this.emit(ChargingStationEvents.started);
- this.starting = false;
+ }
+ )
+ this.started = true
+ this.emit(ChargingStationEvents.started)
+ this.starting = false
} else {
- logger.warn(`${this.logPrefix()} Charging station is already starting...`);
+ logger.warn(`${this.logPrefix()} Charging station is already starting...`)
}
} else {
- logger.warn(`${this.logPrefix()} Charging station is already started...`);
+ logger.warn(`${this.logPrefix()} Charging station is already started...`)
}
}
- public async stop(reason?: StopTransactionReason, stopTransactions?: boolean): Promise<void> {
- if (this.started === true) {
- if (this.stopping === false) {
- this.stopping = true;
- await this.stopMessageSequence(reason, stopTransactions);
- this.closeWSConnection();
+ public async stop (reason?: StopTransactionReason, stopTransactions?: boolean): Promise<void> {
+ if (this.started) {
+ if (!this.stopping) {
+ this.stopping = true
+ await this.stopMessageSequence(reason, stopTransactions)
+ this.closeWSConnection()
if (this.stationInfo?.enableStatistics === true) {
- this.performanceStatistics?.stop();
+ this.performanceStatistics?.stop()
}
- this.sharedLRUCache.deleteChargingStationConfiguration(this.configurationFileHash);
- this.templateFileWatcher?.close();
- this.sharedLRUCache.deleteChargingStationTemplate(this.templateFileHash);
- delete this.bootNotificationResponse;
- this.started = false;
- this.saveConfiguration();
- this.emit(ChargingStationEvents.stopped);
- this.stopping = false;
+ this.sharedLRUCache.deleteChargingStationConfiguration(this.configurationFileHash)
+ this.templateFileWatcher?.close()
+ this.sharedLRUCache.deleteChargingStationTemplate(this.templateFileHash)
+ delete this.bootNotificationResponse
+ this.started = false
+ this.saveConfiguration()
+ this.emit(ChargingStationEvents.stopped)
+ this.stopping = false
} else {
- logger.warn(`${this.logPrefix()} Charging station is already stopping...`);
+ logger.warn(`${this.logPrefix()} Charging station is already stopping...`)
}
} else {
- logger.warn(`${this.logPrefix()} Charging station is already stopped...`);
+ logger.warn(`${this.logPrefix()} Charging station is already stopped...`)
}
}
- public async reset(reason?: StopTransactionReason): Promise<void> {
- await this.stop(reason);
- await sleep(this.stationInfo.resetTime!);
- this.initialize();
- this.start();
+ public async reset (reason?: StopTransactionReason): Promise<void> {
+ await this.stop(reason)
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ await sleep(this.stationInfo.resetTime!)
+ this.initialize()
+ this.start()
}
- public saveOcppConfiguration(): void {
+ public saveOcppConfiguration (): void {
if (this.stationInfo?.ocppPersistentConfiguration === true) {
- this.saveConfiguration();
+ this.saveConfiguration()
}
}
- public bufferMessage(message: string): void {
- this.messageBuffer.add(message);
- this.setIntervalFlushMessageBuffer();
+ public bufferMessage (message: string): void {
+ this.messageBuffer.add(message)
+ this.setIntervalFlushMessageBuffer()
}
- public openWSConnection(
+ public openWSConnection (
options?: WsOptions,
- params?: { closeOpened?: boolean; terminateOpened?: boolean },
+ params?: { closeOpened?: boolean, terminateOpened?: boolean }
): void {
options = {
handshakeTimeout: secondsToMilliseconds(this.getConnectionTimeout()),
...this.stationInfo?.wsOptions,
- ...options,
- };
- params = { ...{ closeOpened: false, terminateOpened: false }, ...params };
+ ...options
+ }
+ params = { ...{ closeOpened: false, terminateOpened: false }, ...params }
if (!checkChargingStation(this, this.logPrefix())) {
- return;
+ return
}
if (
!isNullOrUndefined(this.stationInfo.supervisionUser) &&
!isNullOrUndefined(this.stationInfo.supervisionPassword)
) {
- options.auth = `${this.stationInfo.supervisionUser}:${this.stationInfo.supervisionPassword}`;
+ options.auth = `${this.stationInfo.supervisionUser}:${this.stationInfo.supervisionPassword}`
}
- if (params?.closeOpened) {
- this.closeWSConnection();
+ if (params?.closeOpened === true) {
+ this.closeWSConnection()
}
- if (params?.terminateOpened) {
- this.terminateWSConnection();
+ if (params?.terminateOpened === true) {
+ this.terminateWSConnection()
}
- if (this.isWebSocketConnectionOpened() === true) {
+ if (this.isWebSocketConnectionOpened()) {
logger.warn(
- `${this.logPrefix()} OCPP connection to URL ${this.wsConnectionUrl.toString()} is already opened`,
- );
- return;
+ `${this.logPrefix()} OCPP connection to URL ${this.wsConnectionUrl.toString()} is already opened`
+ )
+ return
}
logger.info(
- `${this.logPrefix()} Open OCPP connection to URL ${this.wsConnectionUrl.toString()}`,
- );
+ `${this.logPrefix()} Open OCPP connection to URL ${this.wsConnectionUrl.toString()}`
+ )
this.wsConnection = new WebSocket(
this.wsConnectionUrl,
`ocpp${this.stationInfo?.ocppVersion}`,
- options,
- );
+ options
+ )
// Handle WebSocket message
this.wsConnection.on(
'message',
- this.onMessage.bind(this) as (this: WebSocket, data: RawData, isBinary: boolean) => void,
- );
+ this.onMessage.bind(this) as (this: WebSocket, data: RawData, isBinary: boolean) => void
+ )
// Handle WebSocket error
this.wsConnection.on(
'error',
- this.onError.bind(this) as (this: WebSocket, error: Error) => void,
- );
+ this.onError.bind(this) as (this: WebSocket, error: Error) => void
+ )
// Handle WebSocket close
this.wsConnection.on(
'close',
- this.onClose.bind(this) as (this: WebSocket, code: number, reason: Buffer) => void,
- );
+ this.onClose.bind(this) as (this: WebSocket, code: number, reason: Buffer) => void
+ )
// Handle WebSocket open
- this.wsConnection.on('open', this.onOpen.bind(this) as (this: WebSocket) => void);
+ this.wsConnection.on('open', this.onOpen.bind(this) as (this: WebSocket) => void)
// Handle WebSocket ping
- this.wsConnection.on('ping', this.onPing.bind(this) as (this: WebSocket, data: Buffer) => void);
+ this.wsConnection.on('ping', this.onPing.bind(this) as (this: WebSocket, data: Buffer) => void)
// Handle WebSocket pong
- this.wsConnection.on('pong', this.onPong.bind(this) as (this: WebSocket, data: Buffer) => void);
+ this.wsConnection.on('pong', this.onPong.bind(this) as (this: WebSocket, data: Buffer) => void)
}
- public closeWSConnection(): void {
- if (this.isWebSocketConnectionOpened() === true) {
- this.wsConnection?.close();
- this.wsConnection = null;
+ public closeWSConnection (): void {
+ if (this.isWebSocketConnectionOpened()) {
+ this.wsConnection?.close()
+ this.wsConnection = null
}
}
- public getAutomaticTransactionGeneratorConfiguration(): AutomaticTransactionGeneratorConfiguration {
+ public getAutomaticTransactionGeneratorConfiguration (): AutomaticTransactionGeneratorConfiguration {
if (isNullOrUndefined(this.automaticTransactionGeneratorConfiguration)) {
let automaticTransactionGeneratorConfiguration:
- | AutomaticTransactionGeneratorConfiguration
- | undefined;
- const stationTemplate = this.getTemplateFromFile();
- const stationConfiguration = this.getConfigurationFromFile();
+ | AutomaticTransactionGeneratorConfiguration
+ | undefined
+ const stationTemplate = this.getTemplateFromFile()
+ const stationConfiguration = this.getConfigurationFromFile()
if (
this.stationInfo?.automaticTransactionGeneratorPersistentConfiguration === true &&
stationConfiguration?.stationInfo?.templateHash === stationTemplate?.templateHash &&
- stationConfiguration?.automaticTransactionGenerator
+ stationConfiguration?.automaticTransactionGenerator != null
) {
automaticTransactionGeneratorConfiguration =
- stationConfiguration?.automaticTransactionGenerator;
+ stationConfiguration?.automaticTransactionGenerator
} else {
- automaticTransactionGeneratorConfiguration = stationTemplate?.AutomaticTransactionGenerator;
+ automaticTransactionGeneratorConfiguration = stationTemplate?.AutomaticTransactionGenerator
}
this.automaticTransactionGeneratorConfiguration = {
...Constants.DEFAULT_ATG_CONFIGURATION,
- ...automaticTransactionGeneratorConfiguration,
- };
+ ...automaticTransactionGeneratorConfiguration
+ }
}
- return this.automaticTransactionGeneratorConfiguration!;
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ return this.automaticTransactionGeneratorConfiguration!
}
- public getAutomaticTransactionGeneratorStatuses(): Status[] | undefined {
- return this.getConfigurationFromFile()?.automaticTransactionGeneratorStatuses;
+ public getAutomaticTransactionGeneratorStatuses (): Status[] | undefined {
+ return this.getConfigurationFromFile()?.automaticTransactionGeneratorStatuses
}
- public startAutomaticTransactionGenerator(connectorIds?: number[]): void {
- this.automaticTransactionGenerator = AutomaticTransactionGenerator.getInstance(this);
+ public startAutomaticTransactionGenerator (connectorIds?: number[]): void {
+ this.automaticTransactionGenerator = AutomaticTransactionGenerator.getInstance(this)
if (isNotEmptyArray(connectorIds)) {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
for (const connectorId of connectorIds!) {
- this.automaticTransactionGenerator?.startConnector(connectorId);
+ this.automaticTransactionGenerator?.startConnector(connectorId)
}
} else {
- this.automaticTransactionGenerator?.start();
+ this.automaticTransactionGenerator?.start()
}
- this.saveAutomaticTransactionGeneratorConfiguration();
- this.emit(ChargingStationEvents.updated);
+ this.saveAutomaticTransactionGeneratorConfiguration()
+ this.emit(ChargingStationEvents.updated)
}
- public stopAutomaticTransactionGenerator(connectorIds?: number[]): void {
+ public stopAutomaticTransactionGenerator (connectorIds?: number[]): void {
if (isNotEmptyArray(connectorIds)) {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
for (const connectorId of connectorIds!) {
- this.automaticTransactionGenerator?.stopConnector(connectorId);
+ this.automaticTransactionGenerator?.stopConnector(connectorId)
}
} else {
- this.automaticTransactionGenerator?.stop();
+ this.automaticTransactionGenerator?.stop()
}
- this.saveAutomaticTransactionGeneratorConfiguration();
- this.emit(ChargingStationEvents.updated);
+ this.saveAutomaticTransactionGeneratorConfiguration()
+ this.emit(ChargingStationEvents.updated)
}
- public async stopTransactionOnConnector(
+ public async stopTransactionOnConnector (
connectorId: number,
- reason?: StopTransactionReason,
+ reason?: StopTransactionReason
): Promise<StopTransactionResponse> {
- const transactionId = this.getConnectorStatus(connectorId)?.transactionId;
+ const transactionId = this.getConnectorStatus(connectorId)?.transactionId
if (
this.stationInfo?.beginEndMeterValues === true &&
this.stationInfo?.ocppStrictCompliance === true &&
const transactionEndMeterValue = buildTransactionEndMeterValue(
this,
connectorId,
- this.getEnergyActiveImportRegisterByTransactionId(transactionId!),
- );
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ this.getEnergyActiveImportRegisterByTransactionId(transactionId!)
+ )
await this.ocppRequestService.requestHandler<MeterValuesRequest, MeterValuesResponse>(
this,
RequestCommand.METER_VALUES,
{
connectorId,
transactionId,
- meterValue: [transactionEndMeterValue],
- },
- );
+ meterValue: [transactionEndMeterValue]
+ }
+ )
}
- return this.ocppRequestService.requestHandler<StopTransactionRequest, StopTransactionResponse>(
- this,
- RequestCommand.STOP_TRANSACTION,
- {
- transactionId,
- meterStop: this.getEnergyActiveImportRegisterByTransactionId(transactionId!, true),
- ...(isNullOrUndefined(reason) && { reason }),
- },
- );
+ return await this.ocppRequestService.requestHandler<
+ StopTransactionRequest,
+ StopTransactionResponse
+ >(this, RequestCommand.STOP_TRANSACTION, {
+ transactionId,
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ meterStop: this.getEnergyActiveImportRegisterByTransactionId(transactionId!, true),
+ ...(isNullOrUndefined(reason) && { reason })
+ })
}
- public getReserveConnectorZeroSupported(): boolean {
+ public getReserveConnectorZeroSupported (): boolean {
return convertToBoolean(
- getConfigurationKey(this, StandardParametersKey.ReserveConnectorZeroSupported)!.value,
- );
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ getConfigurationKey(this, StandardParametersKey.ReserveConnectorZeroSupported)!.value
+ )
}
- public async addReservation(reservation: Reservation): Promise<void> {
- const reservationFound = this.getReservationBy('reservationId', reservation.reservationId);
+ public async addReservation (reservation: Reservation): Promise<void> {
+ const reservationFound = this.getReservationBy('reservationId', reservation.reservationId)
if (reservationFound !== undefined) {
- await this.removeReservation(reservationFound, ReservationTerminationReason.REPLACE_EXISTING);
+ await this.removeReservation(reservationFound, ReservationTerminationReason.REPLACE_EXISTING)
}
- this.getConnectorStatus(reservation.connectorId)!.reservation = reservation;
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ this.getConnectorStatus(reservation.connectorId)!.reservation = reservation
await sendAndSetConnectorStatus(
this,
reservation.connectorId,
ConnectorStatusEnum.Reserved,
undefined,
- { send: reservation.connectorId !== 0 },
- );
+ { send: reservation.connectorId !== 0 }
+ )
}
- public async removeReservation(
+ public async removeReservation (
reservation: Reservation,
- reason: ReservationTerminationReason,
+ reason: ReservationTerminationReason
): Promise<void> {
- const connector = this.getConnectorStatus(reservation.connectorId)!;
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ const connector = this.getConnectorStatus(reservation.connectorId)!
switch (reason) {
case ReservationTerminationReason.CONNECTOR_STATE_CHANGED:
case ReservationTerminationReason.TRANSACTION_STARTED:
- delete connector.reservation;
- break;
+ delete connector.reservation
+ break
case ReservationTerminationReason.RESERVATION_CANCELED:
case ReservationTerminationReason.REPLACE_EXISTING:
case ReservationTerminationReason.EXPIRED:
reservation.connectorId,
ConnectorStatusEnum.Available,
undefined,
- { send: reservation.connectorId !== 0 },
- );
- delete connector.reservation;
- break;
+ { send: reservation.connectorId !== 0 }
+ )
+ delete connector.reservation
+ break
default:
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
- throw new BaseError(`Unknown reservation termination reason '${reason}'`);
+ throw new BaseError(`Unknown reservation termination reason '${reason}'`)
}
}
- public getReservationBy(
+ public getReservationBy (
filterKey: ReservationKey,
- value: number | string,
+ value: number | string
): Reservation | undefined {
if (this.hasEvses) {
for (const evseStatus of this.evses.values()) {
for (const connectorStatus of evseStatus.connectors.values()) {
if (connectorStatus?.reservation?.[filterKey] === value) {
- return connectorStatus.reservation;
+ return connectorStatus.reservation
}
}
}
} else {
for (const connectorStatus of this.connectors.values()) {
if (connectorStatus?.reservation?.[filterKey] === value) {
- return connectorStatus.reservation;
+ return connectorStatus.reservation
}
}
}
}
- public isConnectorReservable(
+ public isConnectorReservable (
reservationId: number,
idTag?: string,
- connectorId?: number,
+ connectorId?: number
): boolean {
- const reservation = this.getReservationBy('reservationId', reservationId);
- const reservationExists = !isUndefined(reservation) && !hasReservationExpired(reservation!);
+ const reservation = this.getReservationBy('reservationId', reservationId)
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ const reservationExists = !isUndefined(reservation) && !hasReservationExpired(reservation!)
if (arguments.length === 1) {
- return !reservationExists;
+ return !reservationExists
} else if (arguments.length > 1) {
const userReservation = !isUndefined(idTag)
- ? this.getReservationBy('idTag', idTag!)
- : undefined;
+ ? // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ this.getReservationBy('idTag', idTag!)
+ : undefined
const userReservationExists =
- !isUndefined(userReservation) && !hasReservationExpired(userReservation!);
- const notConnectorZero = isUndefined(connectorId) ? true : connectorId! > 0;
- const freeConnectorsAvailable = this.getNumberOfReservableConnectors() > 0;
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ !isUndefined(userReservation) && !hasReservationExpired(userReservation!)
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ const notConnectorZero = isUndefined(connectorId) ? true : connectorId! > 0
+ const freeConnectorsAvailable = this.getNumberOfReservableConnectors() > 0
return (
!reservationExists && !userReservationExists && notConnectorZero && freeConnectorsAvailable
- );
+ )
}
- return false;
+ return false
}
- private setIntervalFlushMessageBuffer(): void {
+ private setIntervalFlushMessageBuffer (): void {
if (this.flushMessageBufferSetInterval === undefined) {
this.flushMessageBufferSetInterval = setInterval(() => {
- if (this.isWebSocketConnectionOpened() === true && this.inAcceptedState() === true) {
- this.flushMessageBuffer();
+ if (this.isWebSocketConnectionOpened() && this.inAcceptedState()) {
+ this.flushMessageBuffer()
}
if (this.messageBuffer.size === 0) {
- this.clearIntervalFlushMessageBuffer();
+ this.clearIntervalFlushMessageBuffer()
}
- }, Constants.DEFAULT_MESSAGE_BUFFER_FLUSH_INTERVAL);
+ }, Constants.DEFAULT_MESSAGE_BUFFER_FLUSH_INTERVAL)
}
}
- private clearIntervalFlushMessageBuffer() {
+ private clearIntervalFlushMessageBuffer (): void {
if (this.flushMessageBufferSetInterval !== undefined) {
- clearInterval(this.flushMessageBufferSetInterval);
- delete this.flushMessageBufferSetInterval;
+ clearInterval(this.flushMessageBufferSetInterval)
+ delete this.flushMessageBufferSetInterval
}
}
- private getNumberOfReservableConnectors(): number {
- let numberOfReservableConnectors = 0;
+ private getNumberOfReservableConnectors (): number {
+ let numberOfReservableConnectors = 0
if (this.hasEvses) {
for (const evseStatus of this.evses.values()) {
- numberOfReservableConnectors += getNumberOfReservableConnectors(evseStatus.connectors);
+ numberOfReservableConnectors += getNumberOfReservableConnectors(evseStatus.connectors)
}
} else {
- numberOfReservableConnectors = getNumberOfReservableConnectors(this.connectors);
+ numberOfReservableConnectors = getNumberOfReservableConnectors(this.connectors)
}
- return numberOfReservableConnectors - this.getNumberOfReservationsOnConnectorZero();
+ return numberOfReservableConnectors - this.getNumberOfReservationsOnConnectorZero()
}
- private getNumberOfReservationsOnConnectorZero(): number {
+ private getNumberOfReservationsOnConnectorZero (): number {
if (
- // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
- (this.hasEvses && this.evses.get(0)?.connectors.get(0)?.reservation) ||
- (!this.hasEvses && this.connectors.get(0)?.reservation)
+ (this.hasEvses && this.evses.get(0)?.connectors.get(0)?.reservation != null) ||
+ (!this.hasEvses && this.connectors.get(0)?.reservation != null)
) {
- return 1;
+ return 1
}
- return 0;
+ return 0
}
- private flushMessageBuffer(): void {
+ private flushMessageBuffer (): void {
if (this.messageBuffer.size > 0) {
for (const message of this.messageBuffer.values()) {
- let beginId: string | undefined;
- let commandName: RequestCommand | undefined;
- const [messageType] = JSON.parse(message) as OutgoingRequest | Response | ErrorResponse;
- const isRequest = messageType === MessageType.CALL_MESSAGE;
+ let beginId: string | undefined
+ let commandName: RequestCommand | undefined
+ const [messageType] = JSON.parse(message) as OutgoingRequest | Response | ErrorResponse
+ const isRequest = messageType === MessageType.CALL_MESSAGE
if (isRequest) {
- [, , commandName] = JSON.parse(message) as OutgoingRequest;
- beginId = PerformanceStatistics.beginMeasure(commandName);
+ [, , commandName] = JSON.parse(message) as OutgoingRequest
+ beginId = PerformanceStatistics.beginMeasure(commandName)
}
this.wsConnection?.send(message, (error?: Error) => {
- isRequest && PerformanceStatistics.endMeasure(commandName!, beginId!);
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ isRequest && PerformanceStatistics.endMeasure(commandName!, beginId!)
if (isNullOrUndefined(error)) {
logger.debug(
`${this.logPrefix()} >> Buffered ${getMessageTypeString(
- messageType,
- )} OCPP message sent '${JSON.stringify(message)}'`,
- );
- this.messageBuffer.delete(message);
+ messageType
+ )} OCPP message sent '${JSON.stringify(message)}'`
+ )
+ this.messageBuffer.delete(message)
} else {
logger.debug(
`${this.logPrefix()} >> Buffered ${getMessageTypeString(
- messageType,
+ messageType
)} OCPP message '${JSON.stringify(message)}' send failed:`,
- error,
- );
+ error
+ )
}
- });
+ })
}
}
}
- private getTemplateFromFile(): ChargingStationTemplate | undefined {
- let template: ChargingStationTemplate | undefined;
+ private getTemplateFromFile (): ChargingStationTemplate | undefined {
+ let template: ChargingStationTemplate | undefined
try {
if (this.sharedLRUCache.hasChargingStationTemplate(this.templateFileHash)) {
- template = this.sharedLRUCache.getChargingStationTemplate(this.templateFileHash);
+ template = this.sharedLRUCache.getChargingStationTemplate(this.templateFileHash)
} else {
- const measureId = `${FileType.ChargingStationTemplate} read`;
- const beginId = PerformanceStatistics.beginMeasure(measureId);
- template = JSON.parse(readFileSync(this.templateFile, 'utf8')) as ChargingStationTemplate;
- PerformanceStatistics.endMeasure(measureId, beginId);
+ const measureId = `${FileType.ChargingStationTemplate} read`
+ const beginId = PerformanceStatistics.beginMeasure(measureId)
+ template = JSON.parse(readFileSync(this.templateFile, 'utf8')) as ChargingStationTemplate
+ PerformanceStatistics.endMeasure(measureId, beginId)
template.templateHash = createHash(Constants.DEFAULT_HASH_ALGORITHM)
.update(JSON.stringify(template))
- .digest('hex');
- this.sharedLRUCache.setChargingStationTemplate(template);
- this.templateFileHash = template.templateHash;
+ .digest('hex')
+ this.sharedLRUCache.setChargingStationTemplate(template)
+ this.templateFileHash = template.templateHash
}
} catch (error) {
handleFileException(
this.templateFile,
FileType.ChargingStationTemplate,
error as NodeJS.ErrnoException,
- this.logPrefix(),
- );
- }
- return template;
- }
-
- private getStationInfoFromTemplate(): ChargingStationInfo {
- const stationTemplate: ChargingStationTemplate = this.getTemplateFromFile()!;
- checkTemplate(stationTemplate, this.logPrefix(), this.templateFile);
- const warnTemplateKeysDeprecationOnce = once(warnTemplateKeysDeprecation, this);
- warnTemplateKeysDeprecationOnce(stationTemplate, this.logPrefix(), this.templateFile);
- if (stationTemplate?.Connectors) {
- checkConnectorsConfiguration(stationTemplate, this.logPrefix(), this.templateFile);
- }
- const stationInfo: ChargingStationInfo = stationTemplateToStationInfo(stationTemplate);
- stationInfo.hashId = getHashId(this.index, stationTemplate);
- stationInfo.chargingStationId = getChargingStationId(this.index, stationTemplate);
- stationInfo.ocppVersion = stationTemplate?.ocppVersion ?? OCPPVersion.VERSION_16;
- createSerialNumber(stationTemplate, stationInfo);
- stationInfo.voltageOut = this.getVoltageOut(stationInfo);
+ this.logPrefix()
+ )
+ }
+ return template
+ }
+
+ private getStationInfoFromTemplate (): ChargingStationInfo {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ const stationTemplate: ChargingStationTemplate = this.getTemplateFromFile()!
+ checkTemplate(stationTemplate, this.logPrefix(), this.templateFile)
+ const warnTemplateKeysDeprecationOnce = once(warnTemplateKeysDeprecation, this)
+ warnTemplateKeysDeprecationOnce(stationTemplate, this.logPrefix(), this.templateFile)
+ if (stationTemplate?.Connectors != null) {
+ checkConnectorsConfiguration(stationTemplate, this.logPrefix(), this.templateFile)
+ }
+ const stationInfo: ChargingStationInfo = stationTemplateToStationInfo(stationTemplate)
+ stationInfo.hashId = getHashId(this.index, stationTemplate)
+ stationInfo.chargingStationId = getChargingStationId(this.index, stationTemplate)
+ stationInfo.ocppVersion = stationTemplate?.ocppVersion ?? OCPPVersion.VERSION_16
+ createSerialNumber(stationTemplate, stationInfo)
+ stationInfo.voltageOut = this.getVoltageOut(stationInfo)
if (isNotEmptyArray(stationTemplate?.power)) {
- stationTemplate.power = stationTemplate.power as number[];
- const powerArrayRandomIndex = Math.floor(secureRandom() * stationTemplate.power.length);
+ stationTemplate.power = stationTemplate.power as number[]
+ const powerArrayRandomIndex = Math.floor(secureRandom() * stationTemplate.power.length)
stationInfo.maximumPower =
stationTemplate?.powerUnit === PowerUnits.KILO_WATT
? stationTemplate.power[powerArrayRandomIndex] * 1000
- : stationTemplate.power[powerArrayRandomIndex];
+ : stationTemplate.power[powerArrayRandomIndex]
} else {
- stationTemplate.power = stationTemplate?.power as number;
+ stationTemplate.power = stationTemplate?.power as number
stationInfo.maximumPower =
stationTemplate?.powerUnit === PowerUnits.KILO_WATT
? stationTemplate.power * 1000
- : stationTemplate.power;
+ : stationTemplate.power
}
- stationInfo.maximumAmperage = this.getMaximumAmperage(stationInfo);
+ stationInfo.maximumAmperage = this.getMaximumAmperage(stationInfo)
stationInfo.firmwareVersionPattern =
- stationTemplate?.firmwareVersionPattern ?? Constants.SEMVER_PATTERN;
+ stationTemplate?.firmwareVersionPattern ?? Constants.SEMVER_PATTERN
if (
isNotEmptyString(stationInfo.firmwareVersion) &&
- new RegExp(stationInfo.firmwareVersionPattern).test(stationInfo.firmwareVersion!) === false
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ !new RegExp(stationInfo.firmwareVersionPattern).test(stationInfo.firmwareVersion!)
) {
logger.warn(
`${this.logPrefix()} Firmware version '${stationInfo.firmwareVersion}' in template file ${
this.templateFile
- } does not match firmware version pattern '${stationInfo.firmwareVersionPattern}'`,
- );
+ } does not match firmware version pattern '${stationInfo.firmwareVersionPattern}'`
+ )
}
stationInfo.firmwareUpgrade = merge<FirmwareUpgrade>(
{
versionUpgrade: {
- step: 1,
+ step: 1
},
- reset: true,
+ reset: true
},
- stationTemplate?.firmwareUpgrade ?? {},
- );
+ stationTemplate?.firmwareUpgrade ?? {}
+ )
stationInfo.resetTime = !isNullOrUndefined(stationTemplate?.resetTime)
- ? secondsToMilliseconds(stationTemplate.resetTime!)
- : Constants.CHARGING_STATION_DEFAULT_RESET_TIME;
- return stationInfo;
+ ? // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ secondsToMilliseconds(stationTemplate.resetTime!)
+ : Constants.CHARGING_STATION_DEFAULT_RESET_TIME
+ return stationInfo
}
- private getStationInfoFromFile(
- stationInfoPersistentConfiguration = true,
+ private getStationInfoFromFile (
+ stationInfoPersistentConfiguration = true
): ChargingStationInfo | undefined {
- let stationInfo: ChargingStationInfo | undefined;
- if (stationInfoPersistentConfiguration === true) {
- stationInfo = this.getConfigurationFromFile()?.stationInfo;
- if (stationInfo) {
- delete stationInfo?.infoHash;
+ let stationInfo: ChargingStationInfo | undefined
+ if (stationInfoPersistentConfiguration) {
+ stationInfo = this.getConfigurationFromFile()?.stationInfo
+ if (stationInfo != null) {
+ delete stationInfo?.infoHash
}
}
- return stationInfo;
+ return stationInfo
}
- private getStationInfo(): ChargingStationInfo {
- const defaultStationInfo = Constants.DEFAULT_STATION_INFO;
- const stationInfoFromTemplate: ChargingStationInfo = this.getStationInfoFromTemplate();
+ private getStationInfo (): ChargingStationInfo {
+ const defaultStationInfo = Constants.DEFAULT_STATION_INFO
+ const stationInfoFromTemplate: ChargingStationInfo = this.getStationInfoFromTemplate()
const stationInfoFromFile: ChargingStationInfo | undefined = this.getStationInfoFromFile(
- stationInfoFromTemplate?.stationInfoPersistentConfiguration,
- );
+ stationInfoFromTemplate?.stationInfoPersistentConfiguration
+ )
// Priority:
// 1. charging station info from template
// 2. charging station info from configuration file
if (stationInfoFromFile?.templateHash === stationInfoFromTemplate.templateHash) {
- return { ...defaultStationInfo, ...stationInfoFromFile! };
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ return { ...defaultStationInfo, ...stationInfoFromFile! }
}
- stationInfoFromFile &&
+ stationInfoFromFile != null &&
propagateSerialNumber(
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.getTemplateFromFile()!,
stationInfoFromFile,
- stationInfoFromTemplate,
- );
- return { ...defaultStationInfo, ...stationInfoFromTemplate };
+ stationInfoFromTemplate
+ )
+ return { ...defaultStationInfo, ...stationInfoFromTemplate }
}
- private saveStationInfo(): void {
+ private saveStationInfo (): void {
if (this.stationInfo?.stationInfoPersistentConfiguration === true) {
- this.saveConfiguration();
+ this.saveConfiguration()
}
}
- private handleUnsupportedVersion(version: OCPPVersion | undefined) {
- const errorMsg = `Unsupported protocol version '${version}' configured in template file ${this.templateFile}`;
- logger.error(`${this.logPrefix()} ${errorMsg}`);
- throw new BaseError(errorMsg);
+ private handleUnsupportedVersion (version: OCPPVersion | undefined): void {
+ const errorMsg = `Unsupported protocol version '${version}' configured in template file ${this.templateFile}`
+ logger.error(`${this.logPrefix()} ${errorMsg}`)
+ throw new BaseError(errorMsg)
}
- private initialize(): void {
- const stationTemplate = this.getTemplateFromFile()!;
- checkTemplate(stationTemplate, this.logPrefix(), this.templateFile);
+ private initialize (): void {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ const stationTemplate = this.getTemplateFromFile()!
+ checkTemplate(stationTemplate, this.logPrefix(), this.templateFile)
this.configurationFile = join(
dirname(this.templateFile.replace('station-templates', 'configurations')),
- `${getHashId(this.index, stationTemplate)}.json`,
- );
- const stationConfiguration = this.getConfigurationFromFile();
+ `${getHashId(this.index, stationTemplate)}.json`
+ )
+ const stationConfiguration = this.getConfigurationFromFile()
if (
stationConfiguration?.stationInfo?.templateHash === stationTemplate?.templateHash &&
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
- (stationConfiguration?.connectorsStatus || stationConfiguration?.evsesStatus)
+ (stationConfiguration?.connectorsStatus != null || stationConfiguration?.evsesStatus != null)
) {
- checkConfiguration(stationConfiguration, this.logPrefix(), this.configurationFile);
- this.initializeConnectorsOrEvsesFromFile(stationConfiguration);
+ checkConfiguration(stationConfiguration, this.logPrefix(), this.configurationFile)
+ this.initializeConnectorsOrEvsesFromFile(stationConfiguration)
} else {
- this.initializeConnectorsOrEvsesFromTemplate(stationTemplate);
+ this.initializeConnectorsOrEvsesFromTemplate(stationTemplate)
}
- this.stationInfo = this.getStationInfo();
+ this.stationInfo = this.getStationInfo()
if (
this.stationInfo.firmwareStatus === FirmwareStatus.Installing &&
isNotEmptyString(this.stationInfo.firmwareVersion) &&
) {
const patternGroup: number | undefined =
this.stationInfo.firmwareUpgrade?.versionUpgrade?.patternGroup ??
- this.stationInfo.firmwareVersion?.split('.').length;
+ this.stationInfo.firmwareVersion?.split('.').length
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const match = new RegExp(this.stationInfo.firmwareVersionPattern!)
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
.exec(this.stationInfo.firmwareVersion!)
- ?.slice(1, patternGroup! + 1);
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ ?.slice(1, patternGroup! + 1)
if (!isNullOrUndefined(match)) {
- const patchLevelIndex = match!.length - 1;
- match![patchLevelIndex] = (
- convertToInt(match![patchLevelIndex]) +
- this.stationInfo.firmwareUpgrade!.versionUpgrade!.step!
- ).toString();
- this.stationInfo.firmwareVersion = match!.join('.');
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ const patchLevelIndex = match!.length - 1
+ // prettier-ignore
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ match![patchLevelIndex] = (convertToInt(match![patchLevelIndex]) +
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ this.stationInfo.firmwareUpgrade!.versionUpgrade!.step!).toString()
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ this.stationInfo.firmwareVersion = match!.join('.')
}
}
- this.saveStationInfo();
- this.configuredSupervisionUrl = this.getConfiguredSupervisionUrl();
+ this.saveStationInfo()
+ this.configuredSupervisionUrl = this.getConfiguredSupervisionUrl()
if (this.stationInfo?.enableStatistics === true) {
this.performanceStatistics = PerformanceStatistics.getInstance(
this.stationInfo.hashId,
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.stationInfo.chargingStationId!,
- this.configuredSupervisionUrl,
- );
+ this.configuredSupervisionUrl
+ )
}
- this.bootNotificationRequest = createBootNotificationRequest(this.stationInfo);
- this.powerDivider = this.getPowerDivider();
+ this.bootNotificationRequest = createBootNotificationRequest(this.stationInfo)
+ this.powerDivider = this.getPowerDivider()
// OCPP configuration
- this.ocppConfiguration = this.getOcppConfiguration();
- this.initializeOcppConfiguration();
- this.initializeOcppServices();
+ this.ocppConfiguration = this.getOcppConfiguration()
+ this.initializeOcppConfiguration()
+ this.initializeOcppServices()
this.once(ChargingStationEvents.accepted, () => {
this.startMessageSequence().catch((error) => {
- logger.error(`${this.logPrefix()} Error while starting the message sequence:`, error);
- });
- });
+ logger.error(`${this.logPrefix()} Error while starting the message sequence:`, error)
+ })
+ })
if (this.stationInfo?.autoRegister === true) {
this.bootNotificationResponse = {
currentTime: new Date(),
interval: millisecondsToSeconds(this.getHeartbeatInterval()),
- status: RegistrationStatusEnumType.ACCEPTED,
- };
+ status: RegistrationStatusEnumType.ACCEPTED
+ }
}
}
- private initializeOcppServices(): void {
- const ocppVersion = this.stationInfo?.ocppVersion;
+ private initializeOcppServices (): void {
+ const ocppVersion = this.stationInfo?.ocppVersion
switch (ocppVersion) {
case OCPPVersion.VERSION_16:
this.ocppIncomingRequestService =
- OCPP16IncomingRequestService.getInstance<OCPP16IncomingRequestService>();
+ OCPP16IncomingRequestService.getInstance<OCPP16IncomingRequestService>()
this.ocppRequestService = OCPP16RequestService.getInstance<OCPP16RequestService>(
- OCPP16ResponseService.getInstance<OCPP16ResponseService>(),
- );
- break;
+ OCPP16ResponseService.getInstance<OCPP16ResponseService>()
+ )
+ break
case OCPPVersion.VERSION_20:
case OCPPVersion.VERSION_201:
this.ocppIncomingRequestService =
- OCPP20IncomingRequestService.getInstance<OCPP20IncomingRequestService>();
+ OCPP20IncomingRequestService.getInstance<OCPP20IncomingRequestService>()
this.ocppRequestService = OCPP20RequestService.getInstance<OCPP20RequestService>(
- OCPP20ResponseService.getInstance<OCPP20ResponseService>(),
- );
- break;
+ OCPP20ResponseService.getInstance<OCPP20ResponseService>()
+ )
+ break
default:
- this.handleUnsupportedVersion(ocppVersion);
- break;
+ this.handleUnsupportedVersion(ocppVersion)
+ break
}
}
- private initializeOcppConfiguration(): void {
+ private initializeOcppConfiguration (): void {
if (isNullOrUndefined(getConfigurationKey(this, StandardParametersKey.HeartbeatInterval))) {
- addConfigurationKey(this, StandardParametersKey.HeartbeatInterval, '0');
+ addConfigurationKey(this, StandardParametersKey.HeartbeatInterval, '0')
}
if (isNullOrUndefined(getConfigurationKey(this, StandardParametersKey.HeartBeatInterval))) {
- addConfigurationKey(this, StandardParametersKey.HeartBeatInterval, '0', { visible: false });
+ addConfigurationKey(this, StandardParametersKey.HeartBeatInterval, '0', { visible: false })
}
if (
this.stationInfo?.supervisionUrlOcppConfiguration === true &&
isNotEmptyString(this.stationInfo?.supervisionUrlOcppKey) &&
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
isNullOrUndefined(getConfigurationKey(this, this.stationInfo.supervisionUrlOcppKey!))
) {
addConfigurationKey(
this,
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.stationInfo.supervisionUrlOcppKey!,
this.configuredSupervisionUrl.href,
- { reboot: true },
- );
+ { reboot: true }
+ )
} else if (
this.stationInfo?.supervisionUrlOcppConfiguration === false &&
isNotEmptyString(this.stationInfo?.supervisionUrlOcppKey) &&
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
!isNullOrUndefined(getConfigurationKey(this, this.stationInfo.supervisionUrlOcppKey!))
) {
- deleteConfigurationKey(this, this.stationInfo.supervisionUrlOcppKey!, { save: false });
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ deleteConfigurationKey(this, this.stationInfo.supervisionUrlOcppKey!, { save: false })
}
if (
isNotEmptyString(this.stationInfo?.amperageLimitationOcppKey) &&
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
isNullOrUndefined(getConfigurationKey(this, this.stationInfo.amperageLimitationOcppKey!))
) {
addConfigurationKey(
this,
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.stationInfo.amperageLimitationOcppKey!,
- (
- this.stationInfo.maximumAmperage! * getAmperageLimitationUnitDivider(this.stationInfo)
- ).toString(),
- );
+ // prettier-ignore
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ (this.stationInfo.maximumAmperage! * getAmperageLimitationUnitDivider(this.stationInfo)).toString()
+ )
}
if (
isNullOrUndefined(getConfigurationKey(this, StandardParametersKey.SupportedFeatureProfiles))
addConfigurationKey(
this,
StandardParametersKey.SupportedFeatureProfiles,
- `${SupportedFeatureProfiles.Core},${SupportedFeatureProfiles.FirmwareManagement},${SupportedFeatureProfiles.LocalAuthListManagement},${SupportedFeatureProfiles.SmartCharging},${SupportedFeatureProfiles.RemoteTrigger}`,
- );
+ `${SupportedFeatureProfiles.Core},${SupportedFeatureProfiles.FirmwareManagement},${SupportedFeatureProfiles.LocalAuthListManagement},${SupportedFeatureProfiles.SmartCharging},${SupportedFeatureProfiles.RemoteTrigger}`
+ )
}
addConfigurationKey(
this,
StandardParametersKey.NumberOfConnectors,
this.getNumberOfConnectors().toString(),
{ readonly: true },
- { overwrite: true },
- );
+ { overwrite: true }
+ )
if (
isNullOrUndefined(getConfigurationKey(this, StandardParametersKey.MeterValuesSampledData))
) {
addConfigurationKey(
this,
StandardParametersKey.MeterValuesSampledData,
- MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER,
- );
+ MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER
+ )
}
if (
isNullOrUndefined(getConfigurationKey(this, StandardParametersKey.ConnectorPhaseRotation))
) {
- const connectorsPhaseRotation: string[] = [];
+ const connectorsPhaseRotation: string[] = []
if (this.hasEvses) {
for (const evseStatus of this.evses.values()) {
for (const connectorId of evseStatus.connectors.keys()) {
connectorsPhaseRotation.push(
- getPhaseRotationValue(connectorId, this.getNumberOfPhases())!,
- );
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ getPhaseRotationValue(connectorId, this.getNumberOfPhases())!
+ )
}
}
} else {
for (const connectorId of this.connectors.keys()) {
connectorsPhaseRotation.push(
- getPhaseRotationValue(connectorId, this.getNumberOfPhases())!,
- );
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ getPhaseRotationValue(connectorId, this.getNumberOfPhases())!
+ )
}
}
addConfigurationKey(
this,
StandardParametersKey.ConnectorPhaseRotation,
- connectorsPhaseRotation.toString(),
- );
+ connectorsPhaseRotation.toString()
+ )
}
if (
isNullOrUndefined(getConfigurationKey(this, StandardParametersKey.AuthorizeRemoteTxRequests))
) {
- addConfigurationKey(this, StandardParametersKey.AuthorizeRemoteTxRequests, 'true');
+ addConfigurationKey(this, StandardParametersKey.AuthorizeRemoteTxRequests, 'true')
}
if (
isNullOrUndefined(getConfigurationKey(this, StandardParametersKey.LocalAuthListEnabled)) &&
getConfigurationKey(this, StandardParametersKey.SupportedFeatureProfiles)?.value?.includes(
- SupportedFeatureProfiles.LocalAuthListManagement,
- )
+ SupportedFeatureProfiles.LocalAuthListManagement
+ ) === true
) {
- addConfigurationKey(this, StandardParametersKey.LocalAuthListEnabled, 'false');
+ addConfigurationKey(this, StandardParametersKey.LocalAuthListEnabled, 'false')
}
if (isNullOrUndefined(getConfigurationKey(this, StandardParametersKey.ConnectionTimeOut))) {
addConfigurationKey(
this,
StandardParametersKey.ConnectionTimeOut,
- Constants.DEFAULT_CONNECTION_TIMEOUT.toString(),
- );
+ Constants.DEFAULT_CONNECTION_TIMEOUT.toString()
+ )
}
- this.saveOcppConfiguration();
+ this.saveOcppConfiguration()
}
- private initializeConnectorsOrEvsesFromFile(configuration: ChargingStationConfiguration): void {
- if (configuration?.connectorsStatus && !configuration?.evsesStatus) {
+ private initializeConnectorsOrEvsesFromFile (configuration: ChargingStationConfiguration): void {
+ if (configuration?.connectorsStatus != null && configuration?.evsesStatus == null) {
for (const [connectorId, connectorStatus] of configuration.connectorsStatus.entries()) {
- this.connectors.set(connectorId, cloneObject<ConnectorStatus>(connectorStatus));
+ this.connectors.set(connectorId, cloneObject<ConnectorStatus>(connectorStatus))
}
- } else if (configuration?.evsesStatus && !configuration?.connectorsStatus) {
+ } else if (configuration?.evsesStatus != null && configuration?.connectorsStatus == null) {
for (const [evseId, evseStatusConfiguration] of configuration.evsesStatus.entries()) {
- const evseStatus = cloneObject<EvseStatusConfiguration>(evseStatusConfiguration);
- delete evseStatus.connectorsStatus;
+ const evseStatus = cloneObject<EvseStatusConfiguration>(evseStatusConfiguration)
+ delete evseStatus.connectorsStatus
this.evses.set(evseId, {
...(evseStatus as EvseStatus),
connectors: new Map<number, ConnectorStatus>(
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
evseStatusConfiguration.connectorsStatus!.map((connectorStatus, connectorId) => [
connectorId,
- connectorStatus,
- ]),
- ),
- });
+ connectorStatus
+ ])
+ )
+ })
}
- } else if (configuration?.evsesStatus && configuration?.connectorsStatus) {
- const errorMsg = `Connectors and evses defined at the same time in configuration file ${this.configurationFile}`;
- logger.error(`${this.logPrefix()} ${errorMsg}`);
- throw new BaseError(errorMsg);
+ } else if (configuration?.evsesStatus != null && configuration?.connectorsStatus != null) {
+ const errorMsg = `Connectors and evses defined at the same time in configuration file ${this.configurationFile}`
+ logger.error(`${this.logPrefix()} ${errorMsg}`)
+ throw new BaseError(errorMsg)
} else {
- const errorMsg = `No connectors or evses defined in configuration file ${this.configurationFile}`;
- logger.error(`${this.logPrefix()} ${errorMsg}`);
- throw new BaseError(errorMsg);
+ const errorMsg = `No connectors or evses defined in configuration file ${this.configurationFile}`
+ logger.error(`${this.logPrefix()} ${errorMsg}`)
+ throw new BaseError(errorMsg)
}
}
- private initializeConnectorsOrEvsesFromTemplate(stationTemplate: ChargingStationTemplate) {
- if (stationTemplate?.Connectors && !stationTemplate?.Evses) {
- this.initializeConnectorsFromTemplate(stationTemplate);
- } else if (stationTemplate?.Evses && !stationTemplate?.Connectors) {
- this.initializeEvsesFromTemplate(stationTemplate);
- } else if (stationTemplate?.Evses && stationTemplate?.Connectors) {
- const errorMsg = `Connectors and evses defined at the same time in template file ${this.templateFile}`;
- logger.error(`${this.logPrefix()} ${errorMsg}`);
- throw new BaseError(errorMsg);
+ private initializeConnectorsOrEvsesFromTemplate (stationTemplate: ChargingStationTemplate): void {
+ if (stationTemplate?.Connectors != null && stationTemplate?.Evses == null) {
+ this.initializeConnectorsFromTemplate(stationTemplate)
+ } else if (stationTemplate?.Evses != null && stationTemplate?.Connectors == null) {
+ this.initializeEvsesFromTemplate(stationTemplate)
+ } else if (stationTemplate?.Evses != null && stationTemplate?.Connectors != null) {
+ const errorMsg = `Connectors and evses defined at the same time in template file ${this.templateFile}`
+ logger.error(`${this.logPrefix()} ${errorMsg}`)
+ throw new BaseError(errorMsg)
} else {
- const errorMsg = `No connectors or evses defined in template file ${this.templateFile}`;
- logger.error(`${this.logPrefix()} ${errorMsg}`);
- throw new BaseError(errorMsg);
+ const errorMsg = `No connectors or evses defined in template file ${this.templateFile}`
+ logger.error(`${this.logPrefix()} ${errorMsg}`)
+ throw new BaseError(errorMsg)
}
}
- private initializeConnectorsFromTemplate(stationTemplate: ChargingStationTemplate): void {
- if (!stationTemplate?.Connectors && this.connectors.size === 0) {
- const errorMsg = `No already defined connectors and charging station information from template ${this.templateFile} with no connectors configuration defined`;
- logger.error(`${this.logPrefix()} ${errorMsg}`);
- throw new BaseError(errorMsg);
+ private initializeConnectorsFromTemplate (stationTemplate: ChargingStationTemplate): void {
+ if (stationTemplate?.Connectors == null && this.connectors.size === 0) {
+ const errorMsg = `No already defined connectors and charging station information from template ${this.templateFile} with no connectors configuration defined`
+ logger.error(`${this.logPrefix()} ${errorMsg}`)
+ throw new BaseError(errorMsg)
}
- if (!stationTemplate?.Connectors?.[0]) {
+ if (stationTemplate?.Connectors?.[0] == null) {
logger.warn(
`${this.logPrefix()} Charging station information from template ${
this.templateFile
- } with no connector id 0 configuration`,
- );
+ } with no connector id 0 configuration`
+ )
}
- if (stationTemplate?.Connectors) {
+ if (stationTemplate?.Connectors != null) {
const { configuredMaxConnectors, templateMaxConnectors, templateMaxAvailableConnectors } =
- checkConnectorsConfiguration(stationTemplate, this.logPrefix(), this.templateFile);
+ checkConnectorsConfiguration(stationTemplate, this.logPrefix(), this.templateFile)
const connectorsConfigHash = createHash(Constants.DEFAULT_HASH_ALGORITHM)
.update(
- `${JSON.stringify(stationTemplate?.Connectors)}${configuredMaxConnectors.toString()}`,
+ `${JSON.stringify(stationTemplate?.Connectors)}${configuredMaxConnectors.toString()}`
)
- .digest('hex');
+ .digest('hex')
const connectorsConfigChanged =
- this.connectors?.size !== 0 && this.connectorsConfigurationHash !== connectorsConfigHash;
+ this.connectors?.size !== 0 && this.connectorsConfigurationHash !== connectorsConfigHash
if (this.connectors?.size === 0 || connectorsConfigChanged) {
- connectorsConfigChanged && this.connectors.clear();
- this.connectorsConfigurationHash = connectorsConfigHash;
+ connectorsConfigChanged && this.connectors.clear()
+ this.connectorsConfigurationHash = connectorsConfigHash
if (templateMaxConnectors > 0) {
for (let connectorId = 0; connectorId <= configuredMaxConnectors; connectorId++) {
if (
connectorId === 0 &&
- (!stationTemplate?.Connectors?.[connectorId] ||
- this.getUseConnectorId0(stationTemplate) === false)
+ (stationTemplate?.Connectors?.[connectorId] == null ||
+ !this.getUseConnectorId0(stationTemplate))
) {
- continue;
+ continue
}
const templateConnectorId =
- connectorId > 0 && stationTemplate?.randomConnectors
+ connectorId > 0 && stationTemplate?.randomConnectors === true
? getRandomInteger(templateMaxAvailableConnectors, 1)
- : connectorId;
- const connectorStatus = stationTemplate?.Connectors[templateConnectorId];
+ : connectorId
+ const connectorStatus = stationTemplate?.Connectors[templateConnectorId]
checkStationInfoConnectorStatus(
templateConnectorId,
connectorStatus,
this.logPrefix(),
- this.templateFile,
- );
- this.connectors.set(connectorId, cloneObject<ConnectorStatus>(connectorStatus));
+ this.templateFile
+ )
+ this.connectors.set(connectorId, cloneObject<ConnectorStatus>(connectorStatus))
}
- initializeConnectorsMapStatus(this.connectors, this.logPrefix());
- this.saveConnectorsStatus();
+ initializeConnectorsMapStatus(this.connectors, this.logPrefix())
+ this.saveConnectorsStatus()
} else {
logger.warn(
`${this.logPrefix()} Charging station information from template ${
this.templateFile
- } with no connectors configuration defined, cannot create connectors`,
- );
+ } with no connectors configuration defined, cannot create connectors`
+ )
}
}
} else {
logger.warn(
`${this.logPrefix()} Charging station information from template ${
this.templateFile
- } with no connectors configuration defined, using already defined connectors`,
- );
+ } with no connectors configuration defined, using already defined connectors`
+ )
}
}
- private initializeEvsesFromTemplate(stationTemplate: ChargingStationTemplate): void {
- if (!stationTemplate?.Evses && this.evses.size === 0) {
- const errorMsg = `No already defined evses and charging station information from template ${this.templateFile} with no evses configuration defined`;
- logger.error(`${this.logPrefix()} ${errorMsg}`);
- throw new BaseError(errorMsg);
+ private initializeEvsesFromTemplate (stationTemplate: ChargingStationTemplate): void {
+ if (stationTemplate?.Evses == null && this.evses.size === 0) {
+ const errorMsg = `No already defined evses and charging station information from template ${this.templateFile} with no evses configuration defined`
+ logger.error(`${this.logPrefix()} ${errorMsg}`)
+ throw new BaseError(errorMsg)
}
- if (!stationTemplate?.Evses?.[0]) {
+ if (stationTemplate?.Evses?.[0] == null) {
logger.warn(
`${this.logPrefix()} Charging station information from template ${
this.templateFile
- } with no evse id 0 configuration`,
- );
+ } with no evse id 0 configuration`
+ )
}
- if (!stationTemplate?.Evses?.[0]?.Connectors?.[0]) {
+ if (stationTemplate?.Evses?.[0]?.Connectors?.[0] == null) {
logger.warn(
`${this.logPrefix()} Charging station information from template ${
this.templateFile
- } with evse id 0 with no connector id 0 configuration`,
- );
+ } with evse id 0 with no connector id 0 configuration`
+ )
}
if (Object.keys(stationTemplate?.Evses?.[0]?.Connectors as object).length > 1) {
logger.warn(
`${this.logPrefix()} Charging station information from template ${
this.templateFile
- } with evse id 0 with more than one connector configuration, only connector id 0 configuration will be used`,
- );
+ } with evse id 0 with more than one connector configuration, only connector id 0 configuration will be used`
+ )
}
- if (stationTemplate?.Evses) {
+ if (stationTemplate?.Evses != null) {
const evsesConfigHash = createHash(Constants.DEFAULT_HASH_ALGORITHM)
.update(JSON.stringify(stationTemplate?.Evses))
- .digest('hex');
+ .digest('hex')
const evsesConfigChanged =
- this.evses?.size !== 0 && this.evsesConfigurationHash !== evsesConfigHash;
+ this.evses?.size !== 0 && this.evsesConfigurationHash !== evsesConfigHash
if (this.evses?.size === 0 || evsesConfigChanged) {
- evsesConfigChanged && this.evses.clear();
- this.evsesConfigurationHash = evsesConfigHash;
- const templateMaxEvses = getMaxNumberOfEvses(stationTemplate?.Evses);
+ evsesConfigChanged && this.evses.clear()
+ this.evsesConfigurationHash = evsesConfigHash
+ const templateMaxEvses = getMaxNumberOfEvses(stationTemplate?.Evses)
if (templateMaxEvses > 0) {
for (const evseKey in stationTemplate.Evses) {
- const evseId = convertToInt(evseKey);
+ const evseId = convertToInt(evseKey)
this.evses.set(evseId, {
connectors: buildConnectorsMap(
stationTemplate?.Evses[evseKey]?.Connectors,
this.logPrefix(),
- this.templateFile,
+ this.templateFile
),
- availability: AvailabilityType.Operative,
- });
- initializeConnectorsMapStatus(this.evses.get(evseId)!.connectors, this.logPrefix());
+ availability: AvailabilityType.Operative
+ })
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ initializeConnectorsMapStatus(this.evses.get(evseId)!.connectors, this.logPrefix())
}
- this.saveEvsesStatus();
+ this.saveEvsesStatus()
} else {
logger.warn(
`${this.logPrefix()} Charging station information from template ${
this.templateFile
- } with no evses configuration defined, cannot create evses`,
- );
+ } with no evses configuration defined, cannot create evses`
+ )
}
}
} else {
logger.warn(
`${this.logPrefix()} Charging station information from template ${
this.templateFile
- } with no evses configuration defined, using already defined evses`,
- );
+ } with no evses configuration defined, using already defined evses`
+ )
}
}
- private getConfigurationFromFile(): ChargingStationConfiguration | undefined {
- let configuration: ChargingStationConfiguration | undefined;
+ private getConfigurationFromFile (): ChargingStationConfiguration | undefined {
+ let configuration: ChargingStationConfiguration | undefined
if (isNotEmptyString(this.configurationFile) && existsSync(this.configurationFile)) {
try {
if (this.sharedLRUCache.hasChargingStationConfiguration(this.configurationFileHash)) {
configuration = this.sharedLRUCache.getChargingStationConfiguration(
- this.configurationFileHash,
- );
+ this.configurationFileHash
+ )
} else {
- const measureId = `${FileType.ChargingStationConfiguration} read`;
- const beginId = PerformanceStatistics.beginMeasure(measureId);
+ const measureId = `${FileType.ChargingStationConfiguration} read`
+ const beginId = PerformanceStatistics.beginMeasure(measureId)
configuration = JSON.parse(
- readFileSync(this.configurationFile, 'utf8'),
- ) as ChargingStationConfiguration;
- PerformanceStatistics.endMeasure(measureId, beginId);
- this.sharedLRUCache.setChargingStationConfiguration(configuration);
- this.configurationFileHash = configuration.configurationHash!;
+ readFileSync(this.configurationFile, 'utf8')
+ ) as ChargingStationConfiguration
+ PerformanceStatistics.endMeasure(measureId, beginId)
+ this.sharedLRUCache.setChargingStationConfiguration(configuration)
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ this.configurationFileHash = configuration.configurationHash!
}
} catch (error) {
handleFileException(
this.configurationFile,
FileType.ChargingStationConfiguration,
error as NodeJS.ErrnoException,
- this.logPrefix(),
- );
+ this.logPrefix()
+ )
}
}
- return configuration;
+ return configuration
}
- private saveAutomaticTransactionGeneratorConfiguration(): void {
+ private saveAutomaticTransactionGeneratorConfiguration (): void {
if (this.stationInfo?.automaticTransactionGeneratorPersistentConfiguration === true) {
- this.saveConfiguration();
+ this.saveConfiguration()
}
}
- private saveConnectorsStatus() {
- this.saveConfiguration();
+ private saveConnectorsStatus (): void {
+ this.saveConfiguration()
}
- private saveEvsesStatus() {
- this.saveConfiguration();
+ private saveEvsesStatus (): void {
+ this.saveConfiguration()
}
- private saveConfiguration(): void {
+ private saveConfiguration (): void {
if (isNotEmptyString(this.configurationFile)) {
try {
if (!existsSync(dirname(this.configurationFile))) {
- mkdirSync(dirname(this.configurationFile), { recursive: true });
+ mkdirSync(dirname(this.configurationFile), { recursive: true })
}
- let configurationData: ChargingStationConfiguration = this.getConfigurationFromFile()
- ? cloneObject<ChargingStationConfiguration>(this.getConfigurationFromFile()!)
- : {};
- if (this.stationInfo?.stationInfoPersistentConfiguration === true && this.stationInfo) {
- configurationData.stationInfo = this.stationInfo;
+ let configurationData: ChargingStationConfiguration =
+ this.getConfigurationFromFile() != null
+ ? // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ cloneObject<ChargingStationConfiguration>(this.getConfigurationFromFile()!)
+ : {}
+ if (
+ this.stationInfo?.stationInfoPersistentConfiguration === true &&
+ this.stationInfo != null
+ ) {
+ configurationData.stationInfo = this.stationInfo
} else {
- delete configurationData.stationInfo;
+ delete configurationData.stationInfo
}
if (
this.stationInfo?.ocppPersistentConfiguration === true &&
Array.isArray(this.ocppConfiguration?.configurationKey)
) {
- configurationData.configurationKey = this.ocppConfiguration?.configurationKey;
+ configurationData.configurationKey = this.ocppConfiguration?.configurationKey
} else {
- delete configurationData.configurationKey;
+ delete configurationData.configurationKey
}
configurationData = merge<ChargingStationConfiguration>(
configurationData,
- buildChargingStationAutomaticTransactionGeneratorConfiguration(this),
- );
+ buildChargingStationAutomaticTransactionGeneratorConfiguration(this)
+ )
if (
- !this.stationInfo?.automaticTransactionGeneratorPersistentConfiguration ||
- !this.getAutomaticTransactionGeneratorConfiguration()
+ this.stationInfo?.automaticTransactionGeneratorPersistentConfiguration === false ||
+ this.getAutomaticTransactionGeneratorConfiguration() == null
) {
- delete configurationData.automaticTransactionGenerator;
+ delete configurationData.automaticTransactionGenerator
}
if (this.connectors.size > 0) {
- configurationData.connectorsStatus = buildConnectorsStatus(this);
+ configurationData.connectorsStatus = buildConnectorsStatus(this)
} else {
- delete configurationData.connectorsStatus;
+ delete configurationData.connectorsStatus
}
if (this.evses.size > 0) {
- configurationData.evsesStatus = buildEvsesStatus(this);
+ configurationData.evsesStatus = buildEvsesStatus(this)
} else {
- delete configurationData.evsesStatus;
+ delete configurationData.evsesStatus
}
- delete configurationData.configurationHash;
+ delete configurationData.configurationHash
const configurationHash = createHash(Constants.DEFAULT_HASH_ALGORITHM)
.update(
JSON.stringify({
configurationKey: configurationData.configurationKey,
automaticTransactionGenerator: configurationData.automaticTransactionGenerator,
...(this.connectors.size > 0 && {
- connectorsStatus: configurationData.connectorsStatus,
+ connectorsStatus: configurationData.connectorsStatus
}),
- ...(this.evses.size > 0 && { evsesStatus: configurationData.evsesStatus }),
- } as ChargingStationConfiguration),
+ ...(this.evses.size > 0 && { evsesStatus: configurationData.evsesStatus })
+ } satisfies ChargingStationConfiguration)
)
- .digest('hex');
+ .digest('hex')
if (this.configurationFileHash !== configurationHash) {
AsyncLock.runExclusive(AsyncLockType.configuration, () => {
- configurationData.configurationHash = configurationHash;
- const measureId = `${FileType.ChargingStationConfiguration} write`;
- const beginId = PerformanceStatistics.beginMeasure(measureId);
+ configurationData.configurationHash = configurationHash
+ const measureId = `${FileType.ChargingStationConfiguration} write`
+ const beginId = PerformanceStatistics.beginMeasure(measureId)
writeFileSync(
this.configurationFile,
JSON.stringify(configurationData, undefined, 2),
- 'utf8',
- );
- PerformanceStatistics.endMeasure(measureId, beginId);
- this.sharedLRUCache.deleteChargingStationConfiguration(this.configurationFileHash);
- this.sharedLRUCache.setChargingStationConfiguration(configurationData);
- this.configurationFileHash = configurationHash;
+ 'utf8'
+ )
+ PerformanceStatistics.endMeasure(measureId, beginId)
+ this.sharedLRUCache.deleteChargingStationConfiguration(this.configurationFileHash)
+ this.sharedLRUCache.setChargingStationConfiguration(configurationData)
+ this.configurationFileHash = configurationHash
}).catch((error) => {
handleFileException(
this.configurationFile,
FileType.ChargingStationConfiguration,
error as NodeJS.ErrnoException,
- this.logPrefix(),
- );
- });
+ this.logPrefix()
+ )
+ })
} else {
logger.debug(
`${this.logPrefix()} Not saving unchanged charging station configuration file ${
this.configurationFile
- }`,
- );
+ }`
+ )
}
} catch (error) {
handleFileException(
this.configurationFile,
FileType.ChargingStationConfiguration,
error as NodeJS.ErrnoException,
- this.logPrefix(),
- );
+ this.logPrefix()
+ )
}
} else {
logger.error(
- `${this.logPrefix()} Trying to save charging station configuration to undefined configuration file`,
- );
+ `${this.logPrefix()} Trying to save charging station configuration to undefined configuration file`
+ )
}
}
- private getOcppConfigurationFromTemplate(): ChargingStationOcppConfiguration | undefined {
- return this.getTemplateFromFile()?.Configuration;
+ private getOcppConfigurationFromTemplate (): ChargingStationOcppConfiguration | undefined {
+ return this.getTemplateFromFile()?.Configuration
}
- private getOcppConfigurationFromFile(): ChargingStationOcppConfiguration | undefined {
- const configurationKey = this.getConfigurationFromFile()?.configurationKey;
+ private getOcppConfigurationFromFile (): ChargingStationOcppConfiguration | undefined {
+ const configurationKey = this.getConfigurationFromFile()?.configurationKey
if (this.stationInfo?.ocppPersistentConfiguration === true && Array.isArray(configurationKey)) {
- return { configurationKey };
+ return { configurationKey }
}
- return undefined;
+ return undefined
}
- private getOcppConfiguration(): ChargingStationOcppConfiguration | undefined {
+ private getOcppConfiguration (): ChargingStationOcppConfiguration | undefined {
let ocppConfiguration: ChargingStationOcppConfiguration | undefined =
- this.getOcppConfigurationFromFile();
- if (!ocppConfiguration) {
- ocppConfiguration = this.getOcppConfigurationFromTemplate();
+ this.getOcppConfigurationFromFile()
+ if (ocppConfiguration == null) {
+ ocppConfiguration = this.getOcppConfigurationFromTemplate()
}
- return ocppConfiguration;
+ return ocppConfiguration
}
- private async onOpen(): Promise<void> {
- if (this.isWebSocketConnectionOpened() === true) {
+ private async onOpen (): Promise<void> {
+ if (this.isWebSocketConnectionOpened()) {
logger.info(
- `${this.logPrefix()} Connection to OCPP server through ${this.wsConnectionUrl.toString()} succeeded`,
- );
- let registrationRetryCount = 0;
- if (this.isRegistered() === false) {
+ `${this.logPrefix()} Connection to OCPP server through ${this.wsConnectionUrl.toString()} succeeded`
+ )
+ let registrationRetryCount = 0
+ if (!this.isRegistered()) {
// Send BootNotification
do {
this.bootNotificationResponse = await this.ocppRequestService.requestHandler<
- BootNotificationRequest,
- BootNotificationResponse
+ BootNotificationRequest,
+ BootNotificationResponse
>(this, RequestCommand.BOOT_NOTIFICATION, this.bootNotificationRequest, {
- skipBufferingOnError: true,
- });
- if (this.isRegistered() === false) {
- this.stationInfo?.registrationMaxRetries !== -1 && ++registrationRetryCount;
+ skipBufferingOnError: true
+ })
+ if (!this.isRegistered()) {
+ this.stationInfo?.registrationMaxRetries !== -1 && ++registrationRetryCount
await sleep(
- this?.bootNotificationResponse?.interval
+ this?.bootNotificationResponse?.interval != null
? secondsToMilliseconds(this.bootNotificationResponse.interval)
- : Constants.DEFAULT_BOOT_NOTIFICATION_INTERVAL,
- );
+ : Constants.DEFAULT_BOOT_NOTIFICATION_INTERVAL
+ )
}
} while (
- this.isRegistered() === false &&
+ !this.isRegistered() &&
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
(registrationRetryCount <= this.stationInfo.registrationMaxRetries! ||
this.stationInfo?.registrationMaxRetries === -1)
- );
+ )
}
- if (this.isRegistered() === true) {
- this.emit(ChargingStationEvents.registered);
- if (this.inAcceptedState() === true) {
- this.emit(ChargingStationEvents.accepted);
+ if (this.isRegistered()) {
+ this.emit(ChargingStationEvents.registered)
+ if (this.inAcceptedState()) {
+ this.emit(ChargingStationEvents.accepted)
}
} else {
logger.error(
`${this.logPrefix()} Registration failure: maximum retries reached (${registrationRetryCount}) or retry disabled (${this
- .stationInfo?.registrationMaxRetries})`,
- );
+ .stationInfo?.registrationMaxRetries})`
+ )
}
- this.autoReconnectRetryCount = 0;
- this.emit(ChargingStationEvents.updated);
+ this.autoReconnectRetryCount = 0
+ this.emit(ChargingStationEvents.updated)
} else {
logger.warn(
- `${this.logPrefix()} Connection to OCPP server through ${this.wsConnectionUrl.toString()} failed`,
- );
+ `${this.logPrefix()} Connection to OCPP server through ${this.wsConnectionUrl.toString()} failed`
+ )
}
}
- private async onClose(code: WebSocketCloseEventStatusCode, reason: Buffer): Promise<void> {
+ private async onClose (code: WebSocketCloseEventStatusCode, reason: Buffer): Promise<void> {
switch (code) {
// Normal close
case WebSocketCloseEventStatusCode.CLOSE_NORMAL:
case WebSocketCloseEventStatusCode.CLOSE_NO_STATUS:
logger.info(
`${this.logPrefix()} WebSocket normally closed with status '${getWebSocketCloseEventStatusString(
- code,
- )}' and reason '${reason.toString()}'`,
- );
- this.autoReconnectRetryCount = 0;
- break;
+ code
+ )}' and reason '${reason.toString()}'`
+ )
+ this.autoReconnectRetryCount = 0
+ break
// Abnormal close
default:
logger.error(
`${this.logPrefix()} WebSocket abnormally closed with status '${getWebSocketCloseEventStatusString(
- code,
- )}' and reason '${reason.toString()}'`,
- );
- this.started === true && (await this.reconnect());
- break;
+ code
+ )}' and reason '${reason.toString()}'`
+ )
+ this.started && (await this.reconnect())
+ break
}
- this.emit(ChargingStationEvents.updated);
+ this.emit(ChargingStationEvents.updated)
}
- private getCachedRequest(messageType: MessageType, messageId: string): CachedRequest | undefined {
- const cachedRequest = this.requests.get(messageId);
- if (Array.isArray(cachedRequest) === true) {
- return cachedRequest;
+ private getCachedRequest (messageType: MessageType, messageId: string): CachedRequest | undefined {
+ const cachedRequest = this.requests.get(messageId)
+ if (Array.isArray(cachedRequest)) {
+ return cachedRequest
}
throw new OCPPError(
ErrorType.PROTOCOL_ERROR,
`Cached request for message id ${messageId} ${getMessageTypeString(
- messageType,
+ messageType
)} is not an array`,
undefined,
- cachedRequest,
- );
+ cachedRequest
+ )
}
- private async handleIncomingMessage(request: IncomingRequest): Promise<void> {
- const [messageType, messageId, commandName, commandPayload] = request;
+ private async handleIncomingMessage (request: IncomingRequest): Promise<void> {
+ const [messageType, messageId, commandName, commandPayload] = request
if (this.stationInfo?.enableStatistics === true) {
- this.performanceStatistics?.addRequestStatistic(commandName, messageType);
+ this.performanceStatistics?.addRequestStatistic(commandName, messageType)
}
logger.debug(
`${this.logPrefix()} << Command '${commandName}' received request payload: ${JSON.stringify(
- request,
- )}`,
- );
+ request
+ )}`
+ )
// Process the message
await this.ocppIncomingRequestService.incomingRequestHandler(
this,
messageId,
commandName,
- commandPayload,
- );
- this.emit(ChargingStationEvents.updated);
+ commandPayload
+ )
+ this.emit(ChargingStationEvents.updated)
}
- private handleResponseMessage(response: Response): void {
- const [messageType, messageId, commandPayload] = response;
- if (this.requests.has(messageId) === false) {
+ private handleResponseMessage (response: Response): void {
+ const [messageType, messageId, commandPayload] = response
+ if (!this.requests.has(messageId)) {
// Error
throw new OCPPError(
ErrorType.INTERNAL_ERROR,
`Response for unknown message id ${messageId}`,
undefined,
- commandPayload,
- );
+ commandPayload
+ )
}
// Respond
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const [responseCallback, , requestCommandName, requestPayload] = this.getCachedRequest(
messageType,
- messageId,
- )!;
+ messageId
+ )!
logger.debug(
`${this.logPrefix()} << Command '${
requestCommandName ?? Constants.UNKNOWN_COMMAND
- }' received response payload: ${JSON.stringify(response)}`,
- );
- responseCallback(commandPayload, requestPayload);
+ }' received response payload: ${JSON.stringify(response)}`
+ )
+ responseCallback(commandPayload, requestPayload)
}
- private handleErrorMessage(errorResponse: ErrorResponse): void {
- const [messageType, messageId, errorType, errorMessage, errorDetails] = errorResponse;
- if (this.requests.has(messageId) === false) {
+ private handleErrorMessage (errorResponse: ErrorResponse): void {
+ const [messageType, messageId, errorType, errorMessage, errorDetails] = errorResponse
+ if (!this.requests.has(messageId)) {
// Error
throw new OCPPError(
ErrorType.INTERNAL_ERROR,
`Error response for unknown message id ${messageId}`,
undefined,
- { errorType, errorMessage, errorDetails },
- );
+ { errorType, errorMessage, errorDetails }
+ )
}
- const [, errorCallback, requestCommandName] = this.getCachedRequest(messageType, messageId)!;
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ const [, errorCallback, requestCommandName] = this.getCachedRequest(messageType, messageId)!
logger.debug(
`${this.logPrefix()} << Command '${
requestCommandName ?? Constants.UNKNOWN_COMMAND
- }' received error response payload: ${JSON.stringify(errorResponse)}`,
- );
- errorCallback(new OCPPError(errorType, errorMessage, requestCommandName, errorDetails));
+ }' received error response payload: ${JSON.stringify(errorResponse)}`
+ )
+ errorCallback(new OCPPError(errorType, errorMessage, requestCommandName, errorDetails))
}
- private async onMessage(data: RawData): Promise<void> {
- let request: IncomingRequest | Response | ErrorResponse | undefined;
- let messageType: MessageType | undefined;
- let errorMsg: string;
+ private async onMessage (data: RawData): Promise<void> {
+ let request: IncomingRequest | Response | ErrorResponse | undefined
+ let messageType: MessageType | undefined
+ let errorMsg: string
try {
// eslint-disable-next-line @typescript-eslint/no-base-to-string
- request = JSON.parse(data.toString()) as IncomingRequest | Response | ErrorResponse;
- if (Array.isArray(request) === true) {
- [messageType] = request;
+ request = JSON.parse(data.toString()) as IncomingRequest | Response | ErrorResponse
+ if (Array.isArray(request)) {
+ [messageType] = request
// Check the type of message
switch (messageType) {
// Incoming Message
case MessageType.CALL_MESSAGE:
- await this.handleIncomingMessage(request as IncomingRequest);
- break;
+ await this.handleIncomingMessage(request as IncomingRequest)
+ break
// Response Message
case MessageType.CALL_RESULT_MESSAGE:
- this.handleResponseMessage(request as Response);
- break;
+ this.handleResponseMessage(request as Response)
+ break
// Error Message
case MessageType.CALL_ERROR_MESSAGE:
- this.handleErrorMessage(request as ErrorResponse);
- break;
+ this.handleErrorMessage(request as ErrorResponse)
+ break
// Unknown Message
default:
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
- errorMsg = `Wrong message type ${messageType}`;
- logger.error(`${this.logPrefix()} ${errorMsg}`);
- throw new OCPPError(ErrorType.PROTOCOL_ERROR, errorMsg);
+ errorMsg = `Wrong message type ${messageType}`
+ logger.error(`${this.logPrefix()} ${errorMsg}`)
+ throw new OCPPError(ErrorType.PROTOCOL_ERROR, errorMsg)
}
} else {
throw new OCPPError(
'Incoming message is not an array',
undefined,
{
- request,
- },
- );
+ request
+ }
+ )
}
} catch (error) {
- let commandName: IncomingRequestCommand | undefined;
- let requestCommandName: RequestCommand | IncomingRequestCommand | undefined;
- let errorCallback: ErrorCallback;
- const [, messageId] = request!;
+ let commandName: IncomingRequestCommand | undefined
+ let requestCommandName: RequestCommand | IncomingRequestCommand | undefined
+ let errorCallback: ErrorCallback
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ const [, messageId] = request!
switch (messageType) {
case MessageType.CALL_MESSAGE:
- [, , commandName] = request as IncomingRequest;
+ [, , commandName] = request as IncomingRequest
// Send error
- await this.ocppRequestService.sendError(this, messageId, error as OCPPError, commandName);
- break;
+ await this.ocppRequestService.sendError(this, messageId, error as OCPPError, commandName)
+ break
case MessageType.CALL_RESULT_MESSAGE:
case MessageType.CALL_ERROR_MESSAGE:
- if (this.requests.has(messageId) === true) {
- [, errorCallback, requestCommandName] = this.getCachedRequest(messageType, messageId)!;
+ if (this.requests.has(messageId)) {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ [, errorCallback, requestCommandName] = this.getCachedRequest(messageType, messageId)!
// Reject the deferred promise in case of error at response handling (rejecting an already fulfilled promise is a no-op)
- errorCallback(error as OCPPError, false);
+ errorCallback(error as OCPPError, false)
} else {
// Remove the request from the cache in case of error at response handling
- this.requests.delete(messageId);
+ this.requests.delete(messageId)
}
- break;
+ break
}
- if (error instanceof OCPPError === false) {
+ if (!(error instanceof OCPPError)) {
logger.warn(
`${this.logPrefix()} Error thrown at incoming OCPP command '${
commandName ?? requestCommandName ?? Constants.UNKNOWN_COMMAND
// eslint-disable-next-line @typescript-eslint/no-base-to-string
}' message '${data.toString()}' handling is not an OCPPError:`,
- error,
- );
+ error
+ )
}
logger.error(
`${this.logPrefix()} Incoming OCPP command '${
? ` matching cached request '${JSON.stringify(this.requests.get(messageId))}'`
: ''
} processing error:`,
- error,
- );
+ error
+ )
}
}
- private onPing(): void {
- logger.debug(`${this.logPrefix()} Received a WS ping (rfc6455) from the server`);
+ private onPing (): void {
+ logger.debug(`${this.logPrefix()} Received a WS ping (rfc6455) from the server`)
}
- private onPong(): void {
- logger.debug(`${this.logPrefix()} Received a WS pong (rfc6455) from the server`);
+ private onPong (): void {
+ logger.debug(`${this.logPrefix()} Received a WS pong (rfc6455) from the server`)
}
- private onError(error: WSError): void {
- this.closeWSConnection();
- logger.error(`${this.logPrefix()} WebSocket error:`, error);
+ private onError (error: WSError): void {
+ this.closeWSConnection()
+ logger.error(`${this.logPrefix()} WebSocket error:`, error)
}
- private getEnergyActiveImportRegister(connectorStatus: ConnectorStatus, rounded = false): number {
+ private getEnergyActiveImportRegister (connectorStatus: ConnectorStatus, rounded = false): number {
if (this.stationInfo?.meteringPerTransaction === true) {
return (
- (rounded === true
- ? Math.round(connectorStatus.transactionEnergyActiveImportRegisterValue!)
+ (rounded
+ ? // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ Math.round(connectorStatus.transactionEnergyActiveImportRegisterValue!)
: connectorStatus?.transactionEnergyActiveImportRegisterValue) ?? 0
- );
+ )
}
return (
- (rounded === true
- ? Math.round(connectorStatus.energyActiveImportRegisterValue!)
+ (rounded
+ ? // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ Math.round(connectorStatus.energyActiveImportRegisterValue!)
: connectorStatus?.energyActiveImportRegisterValue) ?? 0
- );
+ )
}
- private getUseConnectorId0(stationTemplate?: ChargingStationTemplate): boolean {
- return stationTemplate?.useConnectorId0 ?? true;
+ private getUseConnectorId0 (stationTemplate?: ChargingStationTemplate): boolean {
+ return stationTemplate?.useConnectorId0 ?? true
}
- private async stopRunningTransactions(reason?: StopTransactionReason): Promise<void> {
+ private async stopRunningTransactions (reason?: StopTransactionReason): Promise<void> {
if (this.hasEvses) {
for (const [evseId, evseStatus] of this.evses) {
if (evseId === 0) {
- continue;
+ continue
}
for (const [connectorId, connectorStatus] of evseStatus.connectors) {
if (connectorStatus.transactionStarted === true) {
- await this.stopTransactionOnConnector(connectorId, reason);
+ await this.stopTransactionOnConnector(connectorId, reason)
}
}
}
} else {
for (const connectorId of this.connectors.keys()) {
if (connectorId > 0 && this.getConnectorStatus(connectorId)?.transactionStarted === true) {
- await this.stopTransactionOnConnector(connectorId, reason);
+ await this.stopTransactionOnConnector(connectorId, reason)
}
}
}
}
// 0 for disabling
- private getConnectionTimeout(): number {
+ private getConnectionTimeout (): number {
if (getConfigurationKey(this, StandardParametersKey.ConnectionTimeOut) !== undefined) {
return convertToInt(
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
getConfigurationKey(this, StandardParametersKey.ConnectionTimeOut)!.value! ??
- Constants.DEFAULT_CONNECTION_TIMEOUT,
- );
+ Constants.DEFAULT_CONNECTION_TIMEOUT
+ )
}
- return Constants.DEFAULT_CONNECTION_TIMEOUT;
+ return Constants.DEFAULT_CONNECTION_TIMEOUT
}
- private getPowerDivider(): number {
- let powerDivider = this.hasEvses ? this.getNumberOfEvses() : this.getNumberOfConnectors();
+ private getPowerDivider (): number {
+ let powerDivider = this.hasEvses ? this.getNumberOfEvses() : this.getNumberOfConnectors()
if (this.stationInfo?.powerSharedByConnectors === true) {
- powerDivider = this.getNumberOfRunningTransactions();
+ powerDivider = this.getNumberOfRunningTransactions()
}
- return powerDivider;
+ return powerDivider
}
- private getMaximumAmperage(stationInfo?: ChargingStationInfo): number | undefined {
- const maximumPower = (stationInfo ?? this.stationInfo).maximumPower!;
+ private getMaximumAmperage (stationInfo?: ChargingStationInfo): number | undefined {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ const maximumPower = (stationInfo ?? this.stationInfo).maximumPower!
switch (this.getCurrentOutType(stationInfo)) {
case CurrentType.AC:
return ACElectricUtils.amperagePerPhaseFromPower(
this.getNumberOfPhases(stationInfo),
maximumPower / (this.hasEvses ? this.getNumberOfEvses() : this.getNumberOfConnectors()),
- this.getVoltageOut(stationInfo),
- );
+ this.getVoltageOut(stationInfo)
+ )
case CurrentType.DC:
- return DCElectricUtils.amperage(maximumPower, this.getVoltageOut(stationInfo));
+ return DCElectricUtils.amperage(maximumPower, this.getVoltageOut(stationInfo))
}
}
- private getCurrentOutType(stationInfo?: ChargingStationInfo): CurrentType {
- return (stationInfo ?? this.stationInfo).currentOutType ?? CurrentType.AC;
+ private getCurrentOutType (stationInfo?: ChargingStationInfo): CurrentType {
+ return (stationInfo ?? this.stationInfo).currentOutType ?? CurrentType.AC
}
- private getVoltageOut(stationInfo?: ChargingStationInfo): Voltage {
+ private getVoltageOut (stationInfo?: ChargingStationInfo): Voltage {
return (
(stationInfo ?? this.stationInfo).voltageOut ??
getDefaultVoltageOut(this.getCurrentOutType(stationInfo), this.logPrefix(), this.templateFile)
- );
+ )
}
- private getAmperageLimitation(): number | undefined {
+ private getAmperageLimitation (): number | undefined {
if (
isNotEmptyString(this.stationInfo?.amperageLimitationOcppKey) &&
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
getConfigurationKey(this, this.stationInfo.amperageLimitationOcppKey!) !== undefined
) {
return (
convertToInt(
- getConfigurationKey(this, this.stationInfo.amperageLimitationOcppKey!)?.value,
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ getConfigurationKey(this, this.stationInfo.amperageLimitationOcppKey!)?.value
) / getAmperageLimitationUnitDivider(this.stationInfo)
- );
+ )
}
}
- private async startMessageSequence(): Promise<void> {
+ private async startMessageSequence (): Promise<void> {
if (this.stationInfo?.autoRegister === true) {
await this.ocppRequestService.requestHandler<
- BootNotificationRequest,
- BootNotificationResponse
+ BootNotificationRequest,
+ BootNotificationResponse
>(this, RequestCommand.BOOT_NOTIFICATION, this.bootNotificationRequest, {
- skipBufferingOnError: true,
- });
+ skipBufferingOnError: true
+ })
}
// Start WebSocket ping
- this.startWebSocketPing();
+ this.startWebSocketPing()
// Start heartbeat
- this.startHeartbeat();
+ this.startHeartbeat()
// Initialize connectors status
if (this.hasEvses) {
for (const [evseId, evseStatus] of this.evses) {
if (evseId > 0) {
for (const [connectorId, connectorStatus] of evseStatus.connectors) {
- const connectorBootStatus = getBootConnectorStatus(this, connectorId, connectorStatus);
- await sendAndSetConnectorStatus(this, connectorId, connectorBootStatus, evseId);
+ const connectorBootStatus = getBootConnectorStatus(this, connectorId, connectorStatus)
+ await sendAndSetConnectorStatus(this, connectorId, connectorBootStatus, evseId)
}
}
}
const connectorBootStatus = getBootConnectorStatus(
this,
connectorId,
- this.getConnectorStatus(connectorId)!,
- );
- await sendAndSetConnectorStatus(this, connectorId, connectorBootStatus);
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ this.getConnectorStatus(connectorId)!
+ )
+ await sendAndSetConnectorStatus(this, connectorId, connectorBootStatus)
}
}
}
if (this.stationInfo.firmwareStatus === FirmwareStatus.Installing) {
await this.ocppRequestService.requestHandler<
- FirmwareStatusNotificationRequest,
- FirmwareStatusNotificationResponse
+ FirmwareStatusNotificationRequest,
+ FirmwareStatusNotificationResponse
>(this, RequestCommand.FIRMWARE_STATUS_NOTIFICATION, {
- status: FirmwareStatus.Installed,
- });
- this.stationInfo.firmwareStatus = FirmwareStatus.Installed;
+ status: FirmwareStatus.Installed
+ })
+ this.stationInfo.firmwareStatus = FirmwareStatus.Installed
}
// Start the ATG
- if (this.getAutomaticTransactionGeneratorConfiguration().enable === true) {
- this.startAutomaticTransactionGenerator();
+ if (this.getAutomaticTransactionGeneratorConfiguration().enable) {
+ this.startAutomaticTransactionGenerator()
}
- this.flushMessageBuffer();
+ this.flushMessageBuffer()
}
- private async stopMessageSequence(
+ private async stopMessageSequence (
reason?: StopTransactionReason,
- stopTransactions = this.stationInfo?.stopTransactionsOnStopped,
+ stopTransactions = this.stationInfo?.stopTransactionsOnStopped
): Promise<void> {
// Stop WebSocket ping
- this.stopWebSocketPing();
+ this.stopWebSocketPing()
// Stop heartbeat
- this.stopHeartbeat();
+ this.stopHeartbeat()
// Stop the ATG
if (this.automaticTransactionGenerator?.started === true) {
- this.stopAutomaticTransactionGenerator();
+ this.stopAutomaticTransactionGenerator()
}
// Stop ongoing transactions
- stopTransactions && (await this.stopRunningTransactions(reason));
+ stopTransactions === true && (await this.stopRunningTransactions(reason))
if (this.hasEvses) {
for (const [evseId, evseStatus] of this.evses) {
if (evseId > 0) {
for (const [connectorId, connectorStatus] of evseStatus.connectors) {
await this.ocppRequestService.requestHandler<
- StatusNotificationRequest,
- StatusNotificationResponse
+ StatusNotificationRequest,
+ StatusNotificationResponse
>(
this,
RequestCommand.STATUS_NOTIFICATION,
this,
connectorId,
ConnectorStatusEnum.Unavailable,
- evseId,
- ),
- );
- delete connectorStatus?.status;
+ evseId
+ )
+ )
+ delete connectorStatus?.status
}
}
}
for (const connectorId of this.connectors.keys()) {
if (connectorId > 0) {
await this.ocppRequestService.requestHandler<
- StatusNotificationRequest,
- StatusNotificationResponse
+ StatusNotificationRequest,
+ StatusNotificationResponse
>(
this,
RequestCommand.STATUS_NOTIFICATION,
- buildStatusNotificationRequest(this, connectorId, ConnectorStatusEnum.Unavailable),
- );
- delete this.getConnectorStatus(connectorId)?.status;
+ buildStatusNotificationRequest(this, connectorId, ConnectorStatusEnum.Unavailable)
+ )
+ delete this.getConnectorStatus(connectorId)?.status
}
}
}
}
- private startWebSocketPing(): void {
+ private startWebSocketPing (): void {
const webSocketPingInterval: number =
getConfigurationKey(this, StandardParametersKey.WebSocketPingInterval) !== undefined
? convertToInt(
- getConfigurationKey(this, StandardParametersKey.WebSocketPingInterval)?.value,
- )
- : 0;
+ getConfigurationKey(this, StandardParametersKey.WebSocketPingInterval)?.value
+ )
+ : 0
if (webSocketPingInterval > 0 && this.webSocketPingSetInterval === undefined) {
this.webSocketPingSetInterval = setInterval(() => {
- if (this.isWebSocketConnectionOpened() === true) {
- this.wsConnection?.ping();
+ if (this.isWebSocketConnectionOpened()) {
+ this.wsConnection?.ping()
}
- }, secondsToMilliseconds(webSocketPingInterval));
+ }, secondsToMilliseconds(webSocketPingInterval))
logger.info(
`${this.logPrefix()} WebSocket ping started every ${formatDurationSeconds(
- webSocketPingInterval,
- )}`,
- );
+ webSocketPingInterval
+ )}`
+ )
} else if (this.webSocketPingSetInterval !== undefined) {
logger.info(
`${this.logPrefix()} WebSocket ping already started every ${formatDurationSeconds(
- webSocketPingInterval,
- )}`,
- );
+ webSocketPingInterval
+ )}`
+ )
} else {
logger.error(
- `${this.logPrefix()} WebSocket ping interval set to ${webSocketPingInterval}, not starting the WebSocket ping`,
- );
+ `${this.logPrefix()} WebSocket ping interval set to ${webSocketPingInterval}, not starting the WebSocket ping`
+ )
}
}
- private stopWebSocketPing(): void {
+ private stopWebSocketPing (): void {
if (this.webSocketPingSetInterval !== undefined) {
- clearInterval(this.webSocketPingSetInterval);
- delete this.webSocketPingSetInterval;
+ clearInterval(this.webSocketPingSetInterval)
+ delete this.webSocketPingSetInterval
}
}
- private getConfiguredSupervisionUrl(): URL {
- let configuredSupervisionUrl: string;
- const supervisionUrls = this.stationInfo?.supervisionUrls ?? Configuration.getSupervisionUrls();
+ private getConfiguredSupervisionUrl (): URL {
+ let configuredSupervisionUrl: string
+ const supervisionUrls = this.stationInfo?.supervisionUrls ?? Configuration.getSupervisionUrls()
if (isNotEmptyArray(supervisionUrls)) {
- let configuredSupervisionUrlIndex: number;
+ let configuredSupervisionUrlIndex: number
switch (Configuration.getSupervisionUrlDistribution()) {
case SupervisionUrlDistribution.RANDOM:
configuredSupervisionUrlIndex = Math.floor(
- secureRandom() * (supervisionUrls as string[]).length,
- );
- break;
+ secureRandom() * (supervisionUrls as string[]).length
+ )
+ break
case SupervisionUrlDistribution.ROUND_ROBIN:
case SupervisionUrlDistribution.CHARGING_STATION_AFFINITY:
default:
- Object.values(SupervisionUrlDistribution).includes(
- Configuration.getSupervisionUrlDistribution()!,
- ) === false &&
+ !Object.values(SupervisionUrlDistribution).includes(
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ Configuration.getSupervisionUrlDistribution()!
+ ) &&
logger.error(
// eslint-disable-next-line @typescript-eslint/no-base-to-string
`${this.logPrefix()} Unknown supervision url distribution '${Configuration.getSupervisionUrlDistribution()}' from values '${SupervisionUrlDistribution.toString()}', defaulting to ${
SupervisionUrlDistribution.CHARGING_STATION_AFFINITY
- }`,
- );
- configuredSupervisionUrlIndex = (this.index - 1) % (supervisionUrls as string[]).length;
- break;
+ }`
+ )
+ configuredSupervisionUrlIndex = (this.index - 1) % (supervisionUrls as string[]).length
+ break
}
- configuredSupervisionUrl = (supervisionUrls as string[])[configuredSupervisionUrlIndex];
+ configuredSupervisionUrl = (supervisionUrls as string[])[configuredSupervisionUrlIndex]
} else {
- configuredSupervisionUrl = supervisionUrls as string;
+ configuredSupervisionUrl = supervisionUrls as string
}
if (isNotEmptyString(configuredSupervisionUrl)) {
- return new URL(configuredSupervisionUrl);
+ return new URL(configuredSupervisionUrl)
}
- const errorMsg = 'No supervision url(s) configured';
- logger.error(`${this.logPrefix()} ${errorMsg}`);
- throw new BaseError(`${errorMsg}`);
+ const errorMsg = 'No supervision url(s) configured'
+ logger.error(`${this.logPrefix()} ${errorMsg}`)
+ throw new BaseError(`${errorMsg}`)
}
- private stopHeartbeat(): void {
+ private stopHeartbeat (): void {
if (this.heartbeatSetInterval !== undefined) {
- clearInterval(this.heartbeatSetInterval);
- delete this.heartbeatSetInterval;
+ clearInterval(this.heartbeatSetInterval)
+ delete this.heartbeatSetInterval
}
}
- private terminateWSConnection(): void {
- if (this.isWebSocketConnectionOpened() === true) {
- this.wsConnection?.terminate();
- this.wsConnection = null;
+ private terminateWSConnection (): void {
+ if (this.isWebSocketConnectionOpened()) {
+ this.wsConnection?.terminate()
+ this.wsConnection = null
}
}
- private async reconnect(): Promise<void> {
+ private async reconnect (): Promise<void> {
// Stop WebSocket ping
- this.stopWebSocketPing();
+ this.stopWebSocketPing()
// Stop heartbeat
- this.stopHeartbeat();
+ this.stopHeartbeat()
// Stop the ATG if needed
- if (this.getAutomaticTransactionGeneratorConfiguration().stopOnConnectionFailure === true) {
- this.stopAutomaticTransactionGenerator();
+ if (this.getAutomaticTransactionGeneratorConfiguration().stopOnConnectionFailure) {
+ this.stopAutomaticTransactionGenerator()
}
if (
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.autoReconnectRetryCount < this.stationInfo.autoReconnectMaxRetries! ||
this.stationInfo?.autoReconnectMaxRetries === -1
) {
- ++this.autoReconnectRetryCount;
+ ++this.autoReconnectRetryCount
const reconnectDelay =
this.stationInfo?.reconnectExponentialDelay === true
? exponentialDelay(this.autoReconnectRetryCount)
- : secondsToMilliseconds(this.getConnectionTimeout());
- const reconnectDelayWithdraw = 1000;
+ : secondsToMilliseconds(this.getConnectionTimeout())
+ const reconnectDelayWithdraw = 1000
const reconnectTimeout =
- reconnectDelay && reconnectDelay - reconnectDelayWithdraw > 0
+ reconnectDelay != null && reconnectDelay - reconnectDelayWithdraw > 0
? reconnectDelay - reconnectDelayWithdraw
- : 0;
+ : 0
logger.error(
`${this.logPrefix()} WebSocket connection retry in ${roundTo(
reconnectDelay,
- 2,
- )}ms, timeout ${reconnectTimeout}ms`,
- );
- await sleep(reconnectDelay);
+ 2
+ )}ms, timeout ${reconnectTimeout}ms`
+ )
+ await sleep(reconnectDelay)
logger.error(
- `${this.logPrefix()} WebSocket connection retry #${this.autoReconnectRetryCount.toString()}`,
- );
+ `${this.logPrefix()} WebSocket connection retry #${this.autoReconnectRetryCount.toString()}`
+ )
this.openWSConnection(
{
- handshakeTimeout: reconnectTimeout,
+ handshakeTimeout: reconnectTimeout
},
- { closeOpened: true },
- );
+ { closeOpened: true }
+ )
} else if (this.stationInfo?.autoReconnectMaxRetries !== -1) {
logger.error(
`${this.logPrefix()} WebSocket connection retries failure: maximum retries reached (${
this.autoReconnectRetryCount
- }) or retries disabled (${this.stationInfo?.autoReconnectMaxRetries})`,
- );
+ }) or retries disabled (${this.stationInfo?.autoReconnectMaxRetries})`
+ )
}
}
}
// Partial Copyright Jerome Benoit. 2021-2023. All Rights Reserved.
-import { parentPort } from 'node:worker_threads';
+import { parentPort } from 'node:worker_threads'
-import { ThreadWorker } from 'poolifier';
+import { ThreadWorker } from 'poolifier'
-import { ChargingStation } from './ChargingStation.js';
-import { BaseError } from '../exception/index.js';
-import type { ChargingStationWorkerData } from '../types/index.js';
-import { Configuration } from '../utils/index.js';
-import { type WorkerMessage, WorkerMessageEvents } from '../worker/index.js';
+import { ChargingStation } from './ChargingStation.js'
+import { BaseError } from '../exception/index.js'
+import type { ChargingStationWorkerData } from '../types/index.js'
+import { Configuration } from '../utils/index.js'
+import { type WorkerMessage, WorkerMessageEvents } from '../worker/index.js'
/**
* Creates and starts a charging station instance
* @param data - data sent to worker
*/
const startChargingStation = (data?: ChargingStationWorkerData): void => {
- new ChargingStation(data!.index, data!.templateFile).start();
-};
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ new ChargingStation(data!.index, data!.templateFile).start()
+}
+// eslint-disable-next-line @typescript-eslint/no-extraneous-class
class ChargingStationWorker<Data extends ChargingStationWorkerData> {
- constructor() {
+ constructor () {
// Add message listener to create and start charging station from the main thread
parentPort?.on('message', (message: WorkerMessage<Data>) => {
switch (message.event) {
case WorkerMessageEvents.startWorkerElement:
try {
- startChargingStation(message.data);
+ startChargingStation(message.data)
parentPort?.postMessage({
- event: WorkerMessageEvents.startedWorkerElement,
- });
+ event: WorkerMessageEvents.startedWorkerElement
+ })
} catch (error) {
parentPort?.postMessage({
event: WorkerMessageEvents.startWorkerElementError,
data: {
name: (error as Error).name,
message: (error as Error).message,
- stack: (error as Error).stack,
- },
- });
+ stack: (error as Error).stack
+ }
+ })
}
- break;
+ break
default:
throw new BaseError(
`Unknown worker event: '${message.event}' received with data: '${JSON.stringify(
message.data,
undefined,
- 2,
- )}'`,
- );
+ 2
+ )}'`
+ )
}
- });
+ })
}
}
export let chargingStationWorker:
- | ChargingStationWorker<ChargingStationWorkerData>
- | ThreadWorker<ChargingStationWorkerData>;
+| ChargingStationWorker<ChargingStationWorkerData>
+| ThreadWorker<ChargingStationWorkerData>
if (Configuration.workerPoolInUse()) {
- chargingStationWorker = new ThreadWorker<ChargingStationWorkerData>(startChargingStation);
+ chargingStationWorker = new ThreadWorker<ChargingStationWorkerData>(startChargingStation)
} else {
- chargingStationWorker = new ChargingStationWorker<ChargingStationWorkerData>();
+ chargingStationWorker = new ChargingStationWorker<ChargingStationWorkerData>()
}
-import type { ChargingStation } from './ChargingStation.js';
-import type { ConfigurationKey, ConfigurationKeyType } from '../types/index.js';
-import { logger } from '../utils/index.js';
+import type { ChargingStation } from './ChargingStation.js'
+import type { ConfigurationKey, ConfigurationKeyType } from '../types/index.js'
+import { logger } from '../utils/index.js'
interface ConfigurationKeyOptions {
- readonly?: boolean;
- visible?: boolean;
- reboot?: boolean;
+ readonly?: boolean
+ visible?: boolean
+ reboot?: boolean
}
interface DeleteConfigurationKeyParams {
- save?: boolean;
- caseInsensitive?: boolean;
+ save?: boolean
+ caseInsensitive?: boolean
}
interface AddConfigurationKeyParams {
- overwrite?: boolean;
- save?: boolean;
+ overwrite?: boolean
+ save?: boolean
}
export const getConfigurationKey = (
chargingStation: ChargingStation,
key: ConfigurationKeyType,
- caseInsensitive = false,
+ caseInsensitive = false
): ConfigurationKey | undefined => {
return chargingStation.ocppConfiguration?.configurationKey?.find((configElement) => {
if (caseInsensitive) {
- return configElement.key.toLowerCase() === key.toLowerCase();
+ return configElement.key.toLowerCase() === key.toLowerCase()
}
- return configElement.key === key;
- });
-};
+ return configElement.key === key
+ })
+}
export const addConfigurationKey = (
chargingStation: ChargingStation,
key: ConfigurationKeyType,
value: string,
options?: ConfigurationKeyOptions,
- params?: AddConfigurationKeyParams,
+ params?: AddConfigurationKeyParams
): void => {
options = {
...{
readonly: false,
visible: true,
- reboot: false,
+ reboot: false
},
- ...options,
- };
- params = { ...{ overwrite: false, save: false }, ...params };
- let keyFound = getConfigurationKey(chargingStation, key);
+ ...options
+ }
+ params = { ...{ overwrite: false, save: false }, ...params }
+ let keyFound = getConfigurationKey(chargingStation, key)
if (keyFound !== undefined && params?.overwrite === true) {
deleteConfigurationKey(chargingStation, keyFound.key, {
- save: false,
- });
- keyFound = undefined;
+ save: false
+ })
+ keyFound = undefined
}
if (keyFound === undefined) {
chargingStation.ocppConfiguration?.configurationKey?.push({
key,
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
readonly: options.readonly!,
value,
visible: options.visible,
- reboot: options.reboot,
- });
- params?.save && chargingStation.saveOcppConfiguration();
+ reboot: options.reboot
+ })
+ params?.save === true && chargingStation.saveOcppConfiguration()
} else {
logger.error(
`${chargingStation.logPrefix()} Trying to add an already existing configuration key: %j`,
- keyFound,
- );
+ keyFound
+ )
}
-};
+}
export const setConfigurationKeyValue = (
chargingStation: ChargingStation,
key: ConfigurationKeyType,
value: string,
- caseInsensitive = false,
+ caseInsensitive = false
): void => {
- const keyFound = getConfigurationKey(chargingStation, key, caseInsensitive);
+ const keyFound = getConfigurationKey(chargingStation, key, caseInsensitive)
if (keyFound !== undefined) {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
chargingStation.ocppConfiguration!.configurationKey![
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
chargingStation.ocppConfiguration!.configurationKey!.indexOf(keyFound)
- ].value = value;
- chargingStation.saveOcppConfiguration();
+ ].value = value
+ chargingStation.saveOcppConfiguration()
} else {
logger.error(
`${chargingStation.logPrefix()} Trying to set a value on a non existing configuration key: %j`,
- { key, value },
- );
+ { key, value }
+ )
}
-};
+}
export const deleteConfigurationKey = (
chargingStation: ChargingStation,
key: ConfigurationKeyType,
- params?: DeleteConfigurationKeyParams,
+ params?: DeleteConfigurationKeyParams
): ConfigurationKey[] | undefined => {
- params = { ...{ save: true, caseInsensitive: false }, ...params };
- const keyFound = getConfigurationKey(chargingStation, key, params?.caseInsensitive);
+ params = { ...{ save: true, caseInsensitive: false }, ...params }
+ const keyFound = getConfigurationKey(chargingStation, key, params?.caseInsensitive)
if (keyFound !== undefined) {
const deletedConfigurationKey = chargingStation.ocppConfiguration?.configurationKey?.splice(
chargingStation.ocppConfiguration.configurationKey.indexOf(keyFound),
- 1,
- );
- params?.save && chargingStation.saveOcppConfiguration();
- return deletedConfigurationKey;
+ 1
+ )
+ params?.save === true && chargingStation.saveOcppConfiguration()
+ return deletedConfigurationKey
}
-};
+}
-import { createHash, randomBytes } from 'node:crypto';
-import type { EventEmitter } from 'node:events';
-import { basename, dirname, join } from 'node:path';
-import { env } from 'node:process';
-import { fileURLToPath } from 'node:url';
+import { createHash, randomBytes } from 'node:crypto'
+import type { EventEmitter } from 'node:events'
+import { basename, dirname, join } from 'node:path'
+import { env } from 'node:process'
+import { fileURLToPath } from 'node:url'
-import chalk from 'chalk';
+import chalk from 'chalk'
import {
type Interval,
addDays,
isDate,
isPast,
isWithinInterval,
- toDate,
-} from 'date-fns';
-import { maxTime } from 'date-fns/constants';
+ toDate
+} from 'date-fns'
+import { maxTime } from 'date-fns/constants'
-import type { ChargingStation } from './ChargingStation.js';
-import { getConfigurationKey } from './ConfigurationKeyUtils.js';
-import { BaseError } from '../exception/index.js';
+import type { ChargingStation } from './ChargingStation.js'
+import { getConfigurationKey } from './ConfigurationKeyUtils.js'
+import { BaseError } from '../exception/index.js'
import {
AmpereUnits,
AvailabilityType,
type ChargingStationConfiguration,
type ChargingStationInfo,
type ChargingStationTemplate,
- ChargingStationWorkerMessageEvents,
+ type ChargingStationWorkerMessageEvents,
ConnectorPhaseRotation,
type ConnectorStatus,
ConnectorStatusEnum,
type Reservation,
ReservationTerminationReason,
StandardParametersKey,
- SupportedFeatureProfiles,
- Voltage,
-} from '../types/index.js';
+ type SupportedFeatureProfiles,
+ Voltage
+} from '../types/index.js'
import {
ACElectricUtils,
Constants,
isUndefined,
isValidTime,
logger,
- secureRandom,
-} from '../utils/index.js';
+ secureRandom
+} from '../utils/index.js'
-const moduleName = 'Helpers';
+const moduleName = 'Helpers'
export const getChargingStationId = (
index: number,
- stationTemplate: ChargingStationTemplate | undefined,
+ stationTemplate: ChargingStationTemplate | undefined
): string => {
if (stationTemplate === undefined) {
- return "Unknown 'chargingStationId'";
+ return "Unknown 'chargingStationId'"
}
// In case of multiple instances: add instance index to charging station id
- const instanceIndex = env.CF_INSTANCE_INDEX ?? 0;
- const idSuffix = stationTemplate?.nameSuffix ?? '';
- const idStr = `000000000${index.toString()}`;
- return stationTemplate?.fixedName
+ const instanceIndex = env.CF_INSTANCE_INDEX ?? 0
+ const idSuffix = stationTemplate?.nameSuffix ?? ''
+ const idStr = `000000000${index.toString()}`
+ return stationTemplate?.fixedName != null
? stationTemplate.baseName
: `${stationTemplate.baseName}-${instanceIndex.toString()}${idStr.substring(
- idStr.length - 4,
- )}${idSuffix}`;
-};
+ idStr.length - 4
+ )}${idSuffix}`
+}
export const hasReservationExpired = (reservation: Reservation): boolean => {
- return isPast(reservation.expiryDate);
-};
+ return isPast(reservation.expiryDate)
+}
export const removeExpiredReservations = async (
- chargingStation: ChargingStation,
+ chargingStation: ChargingStation
): Promise<void> => {
if (chargingStation.hasEvses) {
for (const evseStatus of chargingStation.evses.values()) {
for (const connectorStatus of evseStatus.connectors.values()) {
- if (connectorStatus.reservation && hasReservationExpired(connectorStatus.reservation)) {
+ if (
+ connectorStatus.reservation != null &&
+ hasReservationExpired(connectorStatus.reservation)
+ ) {
await chargingStation.removeReservation(
connectorStatus.reservation,
- ReservationTerminationReason.EXPIRED,
- );
+ ReservationTerminationReason.EXPIRED
+ )
}
}
}
} else {
for (const connectorStatus of chargingStation.connectors.values()) {
- if (connectorStatus.reservation && hasReservationExpired(connectorStatus.reservation)) {
+ if (
+ connectorStatus.reservation != null &&
+ hasReservationExpired(connectorStatus.reservation)
+ ) {
await chargingStation.removeReservation(
connectorStatus.reservation,
- ReservationTerminationReason.EXPIRED,
- );
+ ReservationTerminationReason.EXPIRED
+ )
}
}
}
-};
+}
export const getNumberOfReservableConnectors = (
- connectors: Map<number, ConnectorStatus>,
+ connectors: Map<number, ConnectorStatus>
): number => {
- let numberOfReservableConnectors = 0;
+ let numberOfReservableConnectors = 0
for (const [connectorId, connectorStatus] of connectors) {
if (connectorId === 0) {
- continue;
+ continue
}
if (connectorStatus.status === ConnectorStatusEnum.Available) {
- ++numberOfReservableConnectors;
+ ++numberOfReservableConnectors
}
}
- return numberOfReservableConnectors;
-};
+ return numberOfReservableConnectors
+}
export const getHashId = (index: number, stationTemplate: ChargingStationTemplate): string => {
const chargingStationInfo = {
chargePointModel: stationTemplate.chargePointModel,
chargePointVendor: stationTemplate.chargePointVendor,
...(!isUndefined(stationTemplate.chargeBoxSerialNumberPrefix) && {
- chargeBoxSerialNumber: stationTemplate.chargeBoxSerialNumberPrefix,
+ chargeBoxSerialNumber: stationTemplate.chargeBoxSerialNumberPrefix
}),
...(!isUndefined(stationTemplate.chargePointSerialNumberPrefix) && {
- chargePointSerialNumber: stationTemplate.chargePointSerialNumberPrefix,
+ chargePointSerialNumber: stationTemplate.chargePointSerialNumberPrefix
}),
...(!isUndefined(stationTemplate.meterSerialNumberPrefix) && {
- meterSerialNumber: stationTemplate.meterSerialNumberPrefix,
+ meterSerialNumber: stationTemplate.meterSerialNumberPrefix
}),
...(!isUndefined(stationTemplate.meterType) && {
- meterType: stationTemplate.meterType,
- }),
- };
+ meterType: stationTemplate.meterType
+ })
+ }
return createHash(Constants.DEFAULT_HASH_ALGORITHM)
.update(`${JSON.stringify(chargingStationInfo)}${getChargingStationId(index, stationTemplate)}`)
- .digest('hex');
-};
+ .digest('hex')
+}
export const checkChargingStation = (
chargingStation: ChargingStation,
- logPrefix: string,
+ logPrefix: string
): boolean => {
- if (chargingStation.started === false && chargingStation.starting === false) {
- logger.warn(`${logPrefix} charging station is stopped, cannot proceed`);
- return false;
+ if (!chargingStation.started && !chargingStation.starting) {
+ logger.warn(`${logPrefix} charging station is stopped, cannot proceed`)
+ return false
}
- return true;
-};
+ return true
+}
export const getPhaseRotationValue = (
connectorId: number,
- numberOfPhases: number,
+ numberOfPhases: number
): string | undefined => {
// AC/DC
if (connectorId === 0 && numberOfPhases === 0) {
- return `${connectorId}.${ConnectorPhaseRotation.RST}`;
+ return `${connectorId}.${ConnectorPhaseRotation.RST}`
} else if (connectorId > 0 && numberOfPhases === 0) {
- return `${connectorId}.${ConnectorPhaseRotation.NotApplicable}`;
+ return `${connectorId}.${ConnectorPhaseRotation.NotApplicable}`
// AC
} else if (connectorId >= 0 && numberOfPhases === 1) {
- return `${connectorId}.${ConnectorPhaseRotation.NotApplicable}`;
+ return `${connectorId}.${ConnectorPhaseRotation.NotApplicable}`
} else if (connectorId >= 0 && numberOfPhases === 3) {
- return `${connectorId}.${ConnectorPhaseRotation.RST}`;
+ return `${connectorId}.${ConnectorPhaseRotation.RST}`
}
-};
+}
export const getMaxNumberOfEvses = (evses: Record<string, EvseTemplate>): number => {
- if (!evses) {
- return -1;
+ if (evses == null) {
+ return -1
}
- return Object.keys(evses).length;
-};
+ return Object.keys(evses).length
+}
const getMaxNumberOfConnectors = (connectors: Record<string, ConnectorStatus>): number => {
- if (!connectors) {
- return -1;
+ if (connectors == null) {
+ return -1
}
- return Object.keys(connectors).length;
-};
+ return Object.keys(connectors).length
+}
export const getBootConnectorStatus = (
chargingStation: ChargingStation,
connectorId: number,
- connectorStatus: ConnectorStatus,
+ connectorStatus: ConnectorStatus
): ConnectorStatusEnum => {
- let connectorBootStatus: ConnectorStatusEnum;
+ let connectorBootStatus: ConnectorStatusEnum
if (
- !connectorStatus?.status &&
- (chargingStation.isChargingStationAvailable() === false ||
- chargingStation.isConnectorAvailable(connectorId) === false)
+ connectorStatus?.status == null &&
+ (!chargingStation.isChargingStationAvailable() ||
+ !chargingStation.isConnectorAvailable(connectorId))
) {
- connectorBootStatus = ConnectorStatusEnum.Unavailable;
- } else if (!connectorStatus?.status && connectorStatus?.bootStatus) {
+ connectorBootStatus = ConnectorStatusEnum.Unavailable
+ } else if (connectorStatus?.status == null && connectorStatus?.bootStatus != null) {
// Set boot status in template at startup
- connectorBootStatus = connectorStatus?.bootStatus;
- } else if (connectorStatus?.status) {
+ connectorBootStatus = connectorStatus?.bootStatus
+ } else if (connectorStatus?.status != null) {
// Set previous status at startup
- connectorBootStatus = connectorStatus?.status;
+ connectorBootStatus = connectorStatus?.status
} else {
// Set default status
- connectorBootStatus = ConnectorStatusEnum.Available;
+ connectorBootStatus = ConnectorStatusEnum.Available
}
- return connectorBootStatus;
-};
+ return connectorBootStatus
+}
export const checkTemplate = (
stationTemplate: ChargingStationTemplate,
logPrefix: string,
- templateFile: string,
+ templateFile: string
): void => {
- if (isNullOrUndefined(stationTemplate)) {
- const errorMsg = `Failed to read charging station template file ${templateFile}`;
- logger.error(`${logPrefix} ${errorMsg}`);
- throw new BaseError(errorMsg);
+ if (stationTemplate == null) {
+ const errorMsg = `Failed to read charging station template file ${templateFile}`
+ logger.error(`${logPrefix} ${errorMsg}`)
+ throw new BaseError(errorMsg)
}
if (isEmptyObject(stationTemplate)) {
- const errorMsg = `Empty charging station information from template file ${templateFile}`;
- logger.error(`${logPrefix} ${errorMsg}`);
- throw new BaseError(errorMsg);
+ const errorMsg = `Empty charging station information from template file ${templateFile}`
+ logger.error(`${logPrefix} ${errorMsg}`)
+ throw new BaseError(errorMsg)
}
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
if (isEmptyObject(stationTemplate.AutomaticTransactionGenerator!)) {
- stationTemplate.AutomaticTransactionGenerator = Constants.DEFAULT_ATG_CONFIGURATION;
+ stationTemplate.AutomaticTransactionGenerator = Constants.DEFAULT_ATG_CONFIGURATION
logger.warn(
`${logPrefix} Empty automatic transaction generator configuration from template file ${templateFile}, set to default: %j`,
- Constants.DEFAULT_ATG_CONFIGURATION,
- );
+ Constants.DEFAULT_ATG_CONFIGURATION
+ )
}
if (isNullOrUndefined(stationTemplate.idTagsFile) || isEmptyString(stationTemplate.idTagsFile)) {
logger.warn(
- `${logPrefix} Missing id tags file in template file ${templateFile}. That can lead to issues with the Automatic Transaction Generator`,
- );
+ `${logPrefix} Missing id tags file in template file ${templateFile}. That can lead to issues with the Automatic Transaction Generator`
+ )
}
-};
+}
export const checkConfiguration = (
stationConfiguration: ChargingStationConfiguration | undefined,
logPrefix: string,
- configurationFile: string,
+ configurationFile: string
): void => {
if (isNullOrUndefined(stationConfiguration)) {
- const errorMsg = `Failed to read charging station configuration file ${configurationFile}`;
- logger.error(`${logPrefix} ${errorMsg}`);
- throw new BaseError(errorMsg);
+ const errorMsg = `Failed to read charging station configuration file ${configurationFile}`
+ logger.error(`${logPrefix} ${errorMsg}`)
+ throw new BaseError(errorMsg)
}
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
if (isEmptyObject(stationConfiguration!)) {
- const errorMsg = `Empty charging station configuration from file ${configurationFile}`;
- logger.error(`${logPrefix} ${errorMsg}`);
- throw new BaseError(errorMsg);
+ const errorMsg = `Empty charging station configuration from file ${configurationFile}`
+ logger.error(`${logPrefix} ${errorMsg}`)
+ throw new BaseError(errorMsg)
}
-};
+}
export const checkConnectorsConfiguration = (
stationTemplate: ChargingStationTemplate,
logPrefix: string,
- templateFile: string,
+ templateFile: string
): {
- configuredMaxConnectors: number;
- templateMaxConnectors: number;
- templateMaxAvailableConnectors: number;
+ configuredMaxConnectors: number
+ templateMaxConnectors: number
+ templateMaxAvailableConnectors: number
} => {
- const configuredMaxConnectors = getConfiguredMaxNumberOfConnectors(stationTemplate);
- checkConfiguredMaxConnectors(configuredMaxConnectors, logPrefix, templateFile);
- const templateMaxConnectors = getMaxNumberOfConnectors(stationTemplate.Connectors!);
- checkTemplateMaxConnectors(templateMaxConnectors, logPrefix, templateFile);
- const templateMaxAvailableConnectors = stationTemplate.Connectors?.[0]
- ? templateMaxConnectors - 1
- : templateMaxConnectors;
+ const configuredMaxConnectors = getConfiguredMaxNumberOfConnectors(stationTemplate)
+ checkConfiguredMaxConnectors(configuredMaxConnectors, logPrefix, templateFile)
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ const templateMaxConnectors = getMaxNumberOfConnectors(stationTemplate.Connectors!)
+ checkTemplateMaxConnectors(templateMaxConnectors, logPrefix, templateFile)
+ const templateMaxAvailableConnectors =
+ stationTemplate.Connectors?.[0] != null ? templateMaxConnectors - 1 : templateMaxConnectors
if (
configuredMaxConnectors > templateMaxAvailableConnectors &&
- !stationTemplate?.randomConnectors
+ stationTemplate?.randomConnectors === false
) {
logger.warn(
- `${logPrefix} Number of connectors exceeds the number of connector configurations in template ${templateFile}, forcing random connector configurations affectation`,
- );
- stationTemplate.randomConnectors = true;
+ `${logPrefix} Number of connectors exceeds the number of connector configurations in template ${templateFile}, forcing random connector configurations affectation`
+ )
+ stationTemplate.randomConnectors = true
}
- return { configuredMaxConnectors, templateMaxConnectors, templateMaxAvailableConnectors };
-};
+ return { configuredMaxConnectors, templateMaxConnectors, templateMaxAvailableConnectors }
+}
export const checkStationInfoConnectorStatus = (
connectorId: number,
connectorStatus: ConnectorStatus,
logPrefix: string,
- templateFile: string,
+ templateFile: string
): void => {
if (!isNullOrUndefined(connectorStatus?.status)) {
logger.warn(
- `${logPrefix} Charging station information from template ${templateFile} with connector id ${connectorId} status configuration defined, undefine it`,
- );
- delete connectorStatus.status;
+ `${logPrefix} Charging station information from template ${templateFile} with connector id ${connectorId} status configuration defined, undefine it`
+ )
+ delete connectorStatus.status
}
-};
+}
export const buildConnectorsMap = (
connectors: Record<string, ConnectorStatus>,
logPrefix: string,
- templateFile: string,
+ templateFile: string
): Map<number, ConnectorStatus> => {
- const connectorsMap = new Map<number, ConnectorStatus>();
+ const connectorsMap = new Map<number, ConnectorStatus>()
if (getMaxNumberOfConnectors(connectors) > 0) {
for (const connector in connectors) {
- const connectorStatus = connectors[connector];
- const connectorId = convertToInt(connector);
- checkStationInfoConnectorStatus(connectorId, connectorStatus, logPrefix, templateFile);
- connectorsMap.set(connectorId, cloneObject<ConnectorStatus>(connectorStatus));
+ const connectorStatus = connectors[connector]
+ const connectorId = convertToInt(connector)
+ checkStationInfoConnectorStatus(connectorId, connectorStatus, logPrefix, templateFile)
+ connectorsMap.set(connectorId, cloneObject<ConnectorStatus>(connectorStatus))
}
} else {
logger.warn(
- `${logPrefix} Charging station information from template ${templateFile} with no connectors, cannot build connectors map`,
- );
+ `${logPrefix} Charging station information from template ${templateFile} with no connectors, cannot build connectors map`
+ )
}
- return connectorsMap;
-};
+ return connectorsMap
+}
export const initializeConnectorsMapStatus = (
connectors: Map<number, ConnectorStatus>,
- logPrefix: string,
+ logPrefix: string
): void => {
for (const connectorId of connectors.keys()) {
if (connectorId > 0 && connectors.get(connectorId)?.transactionStarted === true) {
logger.warn(
`${logPrefix} Connector id ${connectorId} at initialization has a transaction started with id ${connectors.get(
- connectorId,
- )?.transactionId}`,
- );
+ connectorId
+ )?.transactionId}`
+ )
}
if (connectorId === 0) {
- connectors.get(connectorId)!.availability = AvailabilityType.Operative;
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ connectors.get(connectorId)!.availability = AvailabilityType.Operative
if (isUndefined(connectors.get(connectorId)?.chargingProfiles)) {
- connectors.get(connectorId)!.chargingProfiles = [];
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ connectors.get(connectorId)!.chargingProfiles = []
}
} else if (
connectorId > 0 &&
isNullOrUndefined(connectors.get(connectorId)?.transactionStarted)
) {
- initializeConnectorStatus(connectors.get(connectorId)!);
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ initializeConnectorStatus(connectors.get(connectorId)!)
}
}
-};
+}
export const resetConnectorStatus = (connectorStatus: ConnectorStatus): void => {
connectorStatus.chargingProfiles =
- connectorStatus.transactionId && isNotEmptyArray(connectorStatus.chargingProfiles)
+ connectorStatus.transactionId != null && isNotEmptyArray(connectorStatus.chargingProfiles)
? connectorStatus.chargingProfiles?.filter(
- (chargingProfile) => chargingProfile.transactionId !== connectorStatus.transactionId,
- )
- : [];
- connectorStatus.idTagLocalAuthorized = false;
- connectorStatus.idTagAuthorized = false;
- connectorStatus.transactionRemoteStarted = false;
- connectorStatus.transactionStarted = false;
- delete connectorStatus?.transactionStart;
- delete connectorStatus?.transactionId;
- delete connectorStatus?.localAuthorizeIdTag;
- delete connectorStatus?.authorizeIdTag;
- delete connectorStatus?.transactionIdTag;
- connectorStatus.transactionEnergyActiveImportRegisterValue = 0;
- delete connectorStatus?.transactionBeginMeterValue;
-};
+ (chargingProfile) => chargingProfile.transactionId !== connectorStatus.transactionId
+ )
+ : []
+ connectorStatus.idTagLocalAuthorized = false
+ connectorStatus.idTagAuthorized = false
+ connectorStatus.transactionRemoteStarted = false
+ connectorStatus.transactionStarted = false
+ delete connectorStatus?.transactionStart
+ delete connectorStatus?.transactionId
+ delete connectorStatus?.localAuthorizeIdTag
+ delete connectorStatus?.authorizeIdTag
+ delete connectorStatus?.transactionIdTag
+ connectorStatus.transactionEnergyActiveImportRegisterValue = 0
+ delete connectorStatus?.transactionBeginMeterValue
+}
export const createBootNotificationRequest = (
stationInfo: ChargingStationInfo,
- bootReason: BootReasonEnumType = BootReasonEnumType.PowerUp,
+ bootReason: BootReasonEnumType = BootReasonEnumType.PowerUp
): BootNotificationRequest => {
- const ocppVersion = stationInfo.ocppVersion!;
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ const ocppVersion = stationInfo.ocppVersion!
switch (ocppVersion) {
case OCPPVersion.VERSION_16:
return {
chargePointModel: stationInfo.chargePointModel,
chargePointVendor: stationInfo.chargePointVendor,
...(!isUndefined(stationInfo.chargeBoxSerialNumber) && {
- chargeBoxSerialNumber: stationInfo.chargeBoxSerialNumber,
+ chargeBoxSerialNumber: stationInfo.chargeBoxSerialNumber
}),
...(!isUndefined(stationInfo.chargePointSerialNumber) && {
- chargePointSerialNumber: stationInfo.chargePointSerialNumber,
+ chargePointSerialNumber: stationInfo.chargePointSerialNumber
}),
...(!isUndefined(stationInfo.firmwareVersion) && {
- firmwareVersion: stationInfo.firmwareVersion,
+ firmwareVersion: stationInfo.firmwareVersion
}),
...(!isUndefined(stationInfo.iccid) && { iccid: stationInfo.iccid }),
...(!isUndefined(stationInfo.imsi) && { imsi: stationInfo.imsi }),
...(!isUndefined(stationInfo.meterSerialNumber) && {
- meterSerialNumber: stationInfo.meterSerialNumber,
+ meterSerialNumber: stationInfo.meterSerialNumber
}),
...(!isUndefined(stationInfo.meterType) && {
- meterType: stationInfo.meterType,
- }),
- } as OCPP16BootNotificationRequest;
+ meterType: stationInfo.meterType
+ })
+ } satisfies OCPP16BootNotificationRequest
case OCPPVersion.VERSION_20:
case OCPPVersion.VERSION_201:
return {
model: stationInfo.chargePointModel,
vendorName: stationInfo.chargePointVendor,
...(!isUndefined(stationInfo.firmwareVersion) && {
- firmwareVersion: stationInfo.firmwareVersion,
+ firmwareVersion: stationInfo.firmwareVersion
}),
...(!isUndefined(stationInfo.chargeBoxSerialNumber) && {
- serialNumber: stationInfo.chargeBoxSerialNumber,
+ serialNumber: stationInfo.chargeBoxSerialNumber
}),
...((!isUndefined(stationInfo.iccid) || !isUndefined(stationInfo.imsi)) && {
modem: {
...(!isUndefined(stationInfo.iccid) && { iccid: stationInfo.iccid }),
- ...(!isUndefined(stationInfo.imsi) && { imsi: stationInfo.imsi }),
- },
- }),
- },
- } as OCPP20BootNotificationRequest;
+ ...(!isUndefined(stationInfo.imsi) && { imsi: stationInfo.imsi })
+ }
+ })
+ }
+ } satisfies OCPP20BootNotificationRequest
}
-};
+}
export const warnTemplateKeysDeprecation = (
stationTemplate: ChargingStationTemplate,
logPrefix: string,
- templateFile: string,
-) => {
- const templateKeys: { deprecatedKey: string; key?: string }[] = [
+ templateFile: string
+): void => {
+ const templateKeys: Array<{ deprecatedKey: string, key?: string }> = [
{ deprecatedKey: 'supervisionUrl', key: 'supervisionUrls' },
{ deprecatedKey: 'authorizationFile', key: 'idTagsFile' },
{ deprecatedKey: 'payloadSchemaValidation', key: 'ocppStrictCompliance' },
- { deprecatedKey: 'mustAuthorizeAtRemoteStart', key: 'remoteAuthorization' },
- ];
+ { deprecatedKey: 'mustAuthorizeAtRemoteStart', key: 'remoteAuthorization' }
+ ]
for (const templateKey of templateKeys) {
warnDeprecatedTemplateKey(
stationTemplate,
templateKey.deprecatedKey,
logPrefix,
templateFile,
- !isUndefined(templateKey.key) ? `Use '${templateKey.key}' instead` : undefined,
- );
- convertDeprecatedTemplateKey(stationTemplate, templateKey.deprecatedKey, templateKey.key);
+ !isUndefined(templateKey.key) ? `Use '${templateKey.key}' instead` : undefined
+ )
+ convertDeprecatedTemplateKey(stationTemplate, templateKey.deprecatedKey, templateKey.key)
}
-};
+}
export const stationTemplateToStationInfo = (
- stationTemplate: ChargingStationTemplate,
+ stationTemplate: ChargingStationTemplate
): ChargingStationInfo => {
- stationTemplate = cloneObject<ChargingStationTemplate>(stationTemplate);
- delete stationTemplate.power;
- delete stationTemplate.powerUnit;
- delete stationTemplate.Connectors;
- delete stationTemplate.Evses;
- delete stationTemplate.Configuration;
- delete stationTemplate.AutomaticTransactionGenerator;
- delete stationTemplate.chargeBoxSerialNumberPrefix;
- delete stationTemplate.chargePointSerialNumberPrefix;
- delete stationTemplate.meterSerialNumberPrefix;
- return stationTemplate as ChargingStationInfo;
-};
+ stationTemplate = cloneObject<ChargingStationTemplate>(stationTemplate)
+ delete stationTemplate.power
+ delete stationTemplate.powerUnit
+ delete stationTemplate.Connectors
+ delete stationTemplate.Evses
+ delete stationTemplate.Configuration
+ delete stationTemplate.AutomaticTransactionGenerator
+ delete stationTemplate.chargeBoxSerialNumberPrefix
+ delete stationTemplate.chargePointSerialNumberPrefix
+ delete stationTemplate.meterSerialNumberPrefix
+ return stationTemplate as ChargingStationInfo
+}
export const createSerialNumber = (
stationTemplate: ChargingStationTemplate,
stationInfo: ChargingStationInfo,
params?: {
- randomSerialNumberUpperCase?: boolean;
- randomSerialNumber?: boolean;
- },
+ randomSerialNumberUpperCase?: boolean
+ randomSerialNumber?: boolean
+ }
): void => {
- params = { ...{ randomSerialNumberUpperCase: true, randomSerialNumber: true }, ...params };
- const serialNumberSuffix = params?.randomSerialNumber
- ? getRandomSerialNumberSuffix({
- upperCase: params.randomSerialNumberUpperCase,
+ params = { ...{ randomSerialNumberUpperCase: true, randomSerialNumber: true }, ...params }
+ const serialNumberSuffix =
+ params?.randomSerialNumber === true
+ ? getRandomSerialNumberSuffix({
+ upperCase: params.randomSerialNumberUpperCase
})
- : '';
+ : ''
isNotEmptyString(stationTemplate?.chargePointSerialNumberPrefix) &&
- (stationInfo.chargePointSerialNumber = `${stationTemplate.chargePointSerialNumberPrefix}${serialNumberSuffix}`);
+ (stationInfo.chargePointSerialNumber = `${stationTemplate.chargePointSerialNumberPrefix}${serialNumberSuffix}`)
isNotEmptyString(stationTemplate?.chargeBoxSerialNumberPrefix) &&
- (stationInfo.chargeBoxSerialNumber = `${stationTemplate.chargeBoxSerialNumberPrefix}${serialNumberSuffix}`);
+ (stationInfo.chargeBoxSerialNumber = `${stationTemplate.chargeBoxSerialNumberPrefix}${serialNumberSuffix}`)
isNotEmptyString(stationTemplate?.meterSerialNumberPrefix) &&
- (stationInfo.meterSerialNumber = `${stationTemplate.meterSerialNumberPrefix}${serialNumberSuffix}`);
-};
+ (stationInfo.meterSerialNumber = `${stationTemplate.meterSerialNumberPrefix}${serialNumberSuffix}`)
+}
export const propagateSerialNumber = (
stationTemplate: ChargingStationTemplate,
stationInfoSrc: ChargingStationInfo,
- stationInfoDst: ChargingStationInfo,
-) => {
- if (!stationInfoSrc || !stationTemplate) {
+ stationInfoDst: ChargingStationInfo
+): void => {
+ if (stationInfoSrc == null || stationTemplate == null) {
throw new BaseError(
- 'Missing charging station template or existing configuration to propagate serial number',
- );
+ 'Missing charging station template or existing configuration to propagate serial number'
+ )
}
- stationTemplate?.chargePointSerialNumberPrefix && stationInfoSrc?.chargePointSerialNumber
+ stationTemplate?.chargePointSerialNumberPrefix != null &&
+ stationInfoSrc?.chargePointSerialNumber != null
? (stationInfoDst.chargePointSerialNumber = stationInfoSrc.chargePointSerialNumber)
- : stationInfoDst?.chargePointSerialNumber && delete stationInfoDst.chargePointSerialNumber;
- stationTemplate?.chargeBoxSerialNumberPrefix && stationInfoSrc?.chargeBoxSerialNumber
+ : stationInfoDst?.chargePointSerialNumber != null &&
+ delete stationInfoDst.chargePointSerialNumber
+ stationTemplate?.chargeBoxSerialNumberPrefix != null &&
+ stationInfoSrc?.chargeBoxSerialNumber != null
? (stationInfoDst.chargeBoxSerialNumber = stationInfoSrc.chargeBoxSerialNumber)
- : stationInfoDst?.chargeBoxSerialNumber && delete stationInfoDst.chargeBoxSerialNumber;
- stationTemplate?.meterSerialNumberPrefix && stationInfoSrc?.meterSerialNumber
+ : stationInfoDst?.chargeBoxSerialNumber != null && delete stationInfoDst.chargeBoxSerialNumber
+ stationTemplate?.meterSerialNumberPrefix != null && stationInfoSrc?.meterSerialNumber != null
? (stationInfoDst.meterSerialNumber = stationInfoSrc.meterSerialNumber)
- : stationInfoDst?.meterSerialNumber && delete stationInfoDst.meterSerialNumber;
-};
+ : stationInfoDst?.meterSerialNumber != null && delete stationInfoDst.meterSerialNumber
+}
export const hasFeatureProfile = (
chargingStation: ChargingStation,
- featureProfile: SupportedFeatureProfiles,
+ featureProfile: SupportedFeatureProfiles
): boolean | undefined => {
return getConfigurationKey(
chargingStation,
- StandardParametersKey.SupportedFeatureProfiles,
- )?.value?.includes(featureProfile);
-};
+ StandardParametersKey.SupportedFeatureProfiles
+ )?.value?.includes(featureProfile)
+}
export const getAmperageLimitationUnitDivider = (stationInfo: ChargingStationInfo): number => {
- let unitDivider = 1;
+ let unitDivider = 1
switch (stationInfo.amperageLimitationUnit) {
case AmpereUnits.DECI_AMPERE:
- unitDivider = 10;
- break;
+ unitDivider = 10
+ break
case AmpereUnits.CENTI_AMPERE:
- unitDivider = 100;
- break;
+ unitDivider = 100
+ break
case AmpereUnits.MILLI_AMPERE:
- unitDivider = 1000;
- break;
+ unitDivider = 1000
+ break
}
- return unitDivider;
-};
+ return unitDivider
+}
/**
* Gets the connector cloned charging profiles applying a power limitation
*/
export const getConnectorChargingProfiles = (
chargingStation: ChargingStation,
- connectorId: number,
-) => {
+ connectorId: number
+): ChargingProfile[] => {
return cloneObject<ChargingProfile[]>(
(chargingStation.getConnectorStatus(connectorId)?.chargingProfiles ?? [])
.sort((a, b) => b.stackLevel - a.stackLevel)
.concat(
(chargingStation.getConnectorStatus(0)?.chargingProfiles ?? []).sort(
- (a, b) => b.stackLevel - a.stackLevel,
- ),
- ),
- );
-};
+ (a, b) => b.stackLevel - a.stackLevel
+ )
+ )
+ )
+}
export const getChargingStationConnectorChargingProfilesPowerLimit = (
chargingStation: ChargingStation,
- connectorId: number,
+ connectorId: number
): number | undefined => {
- let limit: number | undefined, chargingProfile: ChargingProfile | undefined;
+ let limit: number | undefined, chargingProfile: ChargingProfile | undefined
// Get charging profiles sorted by connector id then stack level
- const chargingProfiles = getConnectorChargingProfiles(chargingStation, connectorId);
+ const chargingProfiles = getConnectorChargingProfiles(chargingStation, connectorId)
if (isNotEmptyArray(chargingProfiles)) {
const result = getLimitFromChargingProfiles(
chargingStation,
connectorId,
chargingProfiles,
- chargingStation.logPrefix(),
- );
+ chargingStation.logPrefix()
+ )
if (!isNullOrUndefined(result)) {
- limit = result?.limit;
- chargingProfile = result?.chargingProfile;
+ limit = result?.limit
+ chargingProfile = result?.chargingProfile
switch (chargingStation.stationInfo?.currentOutType) {
case CurrentType.AC:
limit =
chargingProfile?.chargingSchedule?.chargingRateUnit === ChargingRateUnitType.WATT
? limit
: ACElectricUtils.powerTotal(
- chargingStation.getNumberOfPhases(),
- chargingStation.stationInfo.voltageOut!,
- limit!,
- );
- break;
+ chargingStation.getNumberOfPhases(),
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ chargingStation.stationInfo.voltageOut!,
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ limit!
+ )
+ break
case CurrentType.DC:
limit =
chargingProfile?.chargingSchedule?.chargingRateUnit === ChargingRateUnitType.WATT
? limit
- : DCElectricUtils.power(chargingStation.stationInfo.voltageOut!, limit!);
+ : // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ DCElectricUtils.power(chargingStation.stationInfo.voltageOut!, limit!)
}
const connectorMaximumPower =
- chargingStation.stationInfo.maximumPower! / chargingStation.powerDivider;
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ chargingStation.stationInfo.maximumPower! / chargingStation.powerDivider
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
if (limit! > connectorMaximumPower) {
logger.error(
`${chargingStation.logPrefix()} ${moduleName}.getChargingStationConnectorChargingProfilesPowerLimit: Charging profile id ${chargingProfile?.chargingProfileId} limit ${limit} is greater than connector id ${connectorId} maximum ${connectorMaximumPower}: %j`,
- result,
- );
- limit = connectorMaximumPower;
+ result
+ )
+ limit = connectorMaximumPower
}
}
}
- return limit;
-};
+ return limit
+}
export const getDefaultVoltageOut = (
currentType: CurrentType,
logPrefix: string,
- templateFile: string,
+ templateFile: string
): Voltage => {
- const errorMsg = `Unknown ${currentType} currentOutType in template file ${templateFile}, cannot define default voltage out`;
- let defaultVoltageOut: number;
+ const errorMsg = `Unknown ${currentType} currentOutType in template file ${templateFile}, cannot define default voltage out`
+ let defaultVoltageOut: number
switch (currentType) {
case CurrentType.AC:
- defaultVoltageOut = Voltage.VOLTAGE_230;
- break;
+ defaultVoltageOut = Voltage.VOLTAGE_230
+ break
case CurrentType.DC:
- defaultVoltageOut = Voltage.VOLTAGE_400;
- break;
+ defaultVoltageOut = Voltage.VOLTAGE_400
+ break
default:
- logger.error(`${logPrefix} ${errorMsg}`);
- throw new BaseError(errorMsg);
+ logger.error(`${logPrefix} ${errorMsg}`)
+ throw new BaseError(errorMsg)
}
- return defaultVoltageOut;
-};
+ return defaultVoltageOut
+}
export const getIdTagsFile = (stationInfo: ChargingStationInfo): string | undefined => {
- return (
- stationInfo.idTagsFile &&
- join(dirname(fileURLToPath(import.meta.url)), 'assets', basename(stationInfo.idTagsFile))
- );
-};
+ return stationInfo.idTagsFile != null
+ ? join(dirname(fileURLToPath(import.meta.url)), 'assets', basename(stationInfo.idTagsFile))
+ : undefined
+}
export const waitChargingStationEvents = async (
emitter: EventEmitter,
event: ChargingStationWorkerMessageEvents,
- eventsToWait: number,
+ eventsToWait: number
): Promise<number> => {
- return new Promise<number>((resolve) => {
- let events = 0;
+ return await new Promise<number>((resolve) => {
+ let events = 0
if (eventsToWait === 0) {
- resolve(events);
- return;
+ resolve(events)
+ return
}
emitter.on(event, () => {
- ++events;
+ ++events
if (events === eventsToWait) {
- resolve(events);
+ resolve(events)
}
- });
- });
-};
+ })
+ })
+}
const getConfiguredMaxNumberOfConnectors = (stationTemplate: ChargingStationTemplate): number => {
- let configuredMaxNumberOfConnectors = 0;
- if (isNotEmptyArray(stationTemplate.numberOfConnectors) === true) {
- const numberOfConnectors = stationTemplate.numberOfConnectors as number[];
+ let configuredMaxNumberOfConnectors = 0
+ if (isNotEmptyArray(stationTemplate.numberOfConnectors)) {
+ const numberOfConnectors = stationTemplate.numberOfConnectors as number[]
+ configuredMaxNumberOfConnectors =
+ numberOfConnectors[Math.floor(secureRandom() * numberOfConnectors.length)]
+ } else if (!isUndefined(stationTemplate.numberOfConnectors)) {
+ configuredMaxNumberOfConnectors = stationTemplate.numberOfConnectors as number
+ } else if (stationTemplate.Connectors != null && stationTemplate.Evses == null) {
configuredMaxNumberOfConnectors =
- numberOfConnectors[Math.floor(secureRandom() * numberOfConnectors.length)];
- } else if (isUndefined(stationTemplate.numberOfConnectors) === false) {
- configuredMaxNumberOfConnectors = stationTemplate.numberOfConnectors as number;
- } else if (stationTemplate.Connectors && !stationTemplate.Evses) {
- configuredMaxNumberOfConnectors = stationTemplate.Connectors?.[0]
- ? getMaxNumberOfConnectors(stationTemplate.Connectors) - 1
- : getMaxNumberOfConnectors(stationTemplate.Connectors);
- } else if (stationTemplate.Evses && !stationTemplate.Connectors) {
+ stationTemplate.Connectors?.[0] != null
+ ? getMaxNumberOfConnectors(stationTemplate.Connectors) - 1
+ : getMaxNumberOfConnectors(stationTemplate.Connectors)
+ } else if (stationTemplate.Evses != null && stationTemplate.Connectors == null) {
for (const evse in stationTemplate.Evses) {
if (evse === '0') {
- continue;
+ continue
}
configuredMaxNumberOfConnectors += getMaxNumberOfConnectors(
- stationTemplate.Evses[evse].Connectors,
- );
+ stationTemplate.Evses[evse].Connectors
+ )
}
}
- return configuredMaxNumberOfConnectors;
-};
+ return configuredMaxNumberOfConnectors
+}
const checkConfiguredMaxConnectors = (
configuredMaxConnectors: number,
logPrefix: string,
- templateFile: string,
+ templateFile: string
): void => {
if (configuredMaxConnectors <= 0) {
logger.warn(
- `${logPrefix} Charging station information from template ${templateFile} with ${configuredMaxConnectors} connectors`,
- );
+ `${logPrefix} Charging station information from template ${templateFile} with ${configuredMaxConnectors} connectors`
+ )
}
-};
+}
const checkTemplateMaxConnectors = (
templateMaxConnectors: number,
logPrefix: string,
- templateFile: string,
+ templateFile: string
): void => {
if (templateMaxConnectors === 0) {
logger.warn(
- `${logPrefix} Charging station information from template ${templateFile} with empty connectors configuration`,
- );
+ `${logPrefix} Charging station information from template ${templateFile} with empty connectors configuration`
+ )
} else if (templateMaxConnectors < 0) {
logger.error(
- `${logPrefix} Charging station information from template ${templateFile} with no connectors configuration defined`,
- );
+ `${logPrefix} Charging station information from template ${templateFile} with no connectors configuration defined`
+ )
}
-};
+}
const initializeConnectorStatus = (connectorStatus: ConnectorStatus): void => {
- connectorStatus.availability = AvailabilityType.Operative;
- connectorStatus.idTagLocalAuthorized = false;
- connectorStatus.idTagAuthorized = false;
- connectorStatus.transactionRemoteStarted = false;
- connectorStatus.transactionStarted = false;
- connectorStatus.energyActiveImportRegisterValue = 0;
- connectorStatus.transactionEnergyActiveImportRegisterValue = 0;
+ connectorStatus.availability = AvailabilityType.Operative
+ connectorStatus.idTagLocalAuthorized = false
+ connectorStatus.idTagAuthorized = false
+ connectorStatus.transactionRemoteStarted = false
+ connectorStatus.transactionStarted = false
+ connectorStatus.energyActiveImportRegisterValue = 0
+ connectorStatus.transactionEnergyActiveImportRegisterValue = 0
if (isUndefined(connectorStatus.chargingProfiles)) {
- connectorStatus.chargingProfiles = [];
+ connectorStatus.chargingProfiles = []
}
-};
+}
const warnDeprecatedTemplateKey = (
template: ChargingStationTemplate,
key: string,
logPrefix: string,
templateFile: string,
- logMsgToAppend = '',
+ logMsgToAppend = ''
): void => {
if (!isUndefined(template?.[key as keyof ChargingStationTemplate])) {
const logMsg = `Deprecated template key '${key}' usage in file '${templateFile}'${
isNotEmptyString(logMsgToAppend) ? `. ${logMsgToAppend}` : ''
- }`;
- logger.warn(`${logPrefix} ${logMsg}`);
- console.warn(`${chalk.green(logPrefix)} ${chalk.yellow(logMsg)}`);
+ }`
+ logger.warn(`${logPrefix} ${logMsg}`)
+ console.warn(`${chalk.green(logPrefix)} ${chalk.yellow(logMsg)}`)
}
-};
+}
const convertDeprecatedTemplateKey = (
template: ChargingStationTemplate,
deprecatedKey: string,
- key?: string,
+ key?: string
): void => {
if (!isUndefined(template?.[deprecatedKey as keyof ChargingStationTemplate])) {
if (!isUndefined(key)) {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
(template as unknown as Record<string, unknown>)[key!] =
- template[deprecatedKey as keyof ChargingStationTemplate];
+ template[deprecatedKey as keyof ChargingStationTemplate]
}
- delete template[deprecatedKey as keyof ChargingStationTemplate];
+ // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
+ delete template[deprecatedKey as keyof ChargingStationTemplate]
}
-};
+}
interface ChargingProfilesLimit {
- limit: number;
- chargingProfile: ChargingProfile;
+ limit: number
+ chargingProfile: ChargingProfile
}
/**
chargingStation: ChargingStation,
connectorId: number,
chargingProfiles: ChargingProfile[],
- logPrefix: string,
+ logPrefix: string
): ChargingProfilesLimit | undefined => {
- const debugLogMsg = `${logPrefix} ${moduleName}.getLimitFromChargingProfiles: Matching charging profile found for power limitation: %j`;
- const currentDate = new Date();
- const connectorStatus = chargingStation.getConnectorStatus(connectorId)!;
+ const debugLogMsg = `${logPrefix} ${moduleName}.getLimitFromChargingProfiles: Matching charging profile found for power limitation: %j`
+ const currentDate = new Date()
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ const connectorStatus = chargingStation.getConnectorStatus(connectorId)!
for (const chargingProfile of chargingProfiles) {
- const chargingSchedule = chargingProfile.chargingSchedule;
- if (isNullOrUndefined(chargingSchedule?.startSchedule) && connectorStatus?.transactionStarted) {
+ const chargingSchedule = chargingProfile.chargingSchedule
+ if (
+ isNullOrUndefined(chargingSchedule?.startSchedule) &&
+ connectorStatus?.transactionStarted === true
+ ) {
logger.debug(
- `${logPrefix} ${moduleName}.getLimitFromChargingProfiles: Charging profile id ${chargingProfile.chargingProfileId} has no startSchedule defined. Trying to set it to the connector current transaction start date`,
- );
+ `${logPrefix} ${moduleName}.getLimitFromChargingProfiles: Charging profile id ${chargingProfile.chargingProfileId} has no startSchedule defined. Trying to set it to the connector current transaction start date`
+ )
// OCPP specifies that if startSchedule is not defined, it should be relative to start of the connector transaction
- chargingSchedule.startSchedule = connectorStatus?.transactionStart;
+ chargingSchedule.startSchedule = connectorStatus?.transactionStart
}
if (
!isNullOrUndefined(chargingSchedule?.startSchedule) &&
!isDate(chargingSchedule?.startSchedule)
) {
logger.warn(
- `${logPrefix} ${moduleName}.getLimitFromChargingProfiles: Charging profile id ${chargingProfile.chargingProfileId} startSchedule property is not a Date instance. Trying to convert it to a Date instance`,
- );
- chargingSchedule.startSchedule = convertToDate(chargingSchedule?.startSchedule)!;
+ `${logPrefix} ${moduleName}.getLimitFromChargingProfiles: Charging profile id ${chargingProfile.chargingProfileId} startSchedule property is not a Date instance. Trying to convert it to a Date instance`
+ )
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ chargingSchedule.startSchedule = convertToDate(chargingSchedule?.startSchedule)!
}
if (
!isNullOrUndefined(chargingSchedule?.startSchedule) &&
isNullOrUndefined(chargingSchedule?.duration)
) {
logger.debug(
- `${logPrefix} ${moduleName}.getLimitFromChargingProfiles: Charging profile id ${chargingProfile.chargingProfileId} has no duration defined and will be set to the maximum time allowed`,
- );
+ `${logPrefix} ${moduleName}.getLimitFromChargingProfiles: Charging profile id ${chargingProfile.chargingProfileId} has no duration defined and will be set to the maximum time allowed`
+ )
// OCPP specifies that if duration is not defined, it should be infinite
- chargingSchedule.duration = differenceInSeconds(maxTime, chargingSchedule.startSchedule!);
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ chargingSchedule.duration = differenceInSeconds(maxTime, chargingSchedule.startSchedule!)
}
if (!prepareChargingProfileKind(connectorStatus, chargingProfile, currentDate, logPrefix)) {
- continue;
+ continue
}
if (!canProceedChargingProfile(chargingProfile, currentDate, logPrefix)) {
- continue;
+ continue
}
// Check if the charging profile is active
if (
isWithinInterval(currentDate, {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
start: chargingSchedule.startSchedule!,
- end: addSeconds(chargingSchedule.startSchedule!, chargingSchedule.duration!),
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ end: addSeconds(chargingSchedule.startSchedule!, chargingSchedule.duration!)
})
) {
if (isNotEmptyArray(chargingSchedule.chargingSchedulePeriod)) {
const chargingSchedulePeriodCompareFn = (
a: ChargingSchedulePeriod,
- b: ChargingSchedulePeriod,
- ) => a.startPeriod - b.startPeriod;
+ b: ChargingSchedulePeriod
+ ): number => a.startPeriod - b.startPeriod
if (
!isArraySorted<ChargingSchedulePeriod>(
chargingSchedule.chargingSchedulePeriod,
- chargingSchedulePeriodCompareFn,
+ chargingSchedulePeriodCompareFn
)
) {
logger.warn(
- `${logPrefix} ${moduleName}.getLimitFromChargingProfiles: Charging profile id ${chargingProfile.chargingProfileId} schedule periods are not sorted by start period`,
- );
- chargingSchedule.chargingSchedulePeriod.sort(chargingSchedulePeriodCompareFn);
+ `${logPrefix} ${moduleName}.getLimitFromChargingProfiles: Charging profile id ${chargingProfile.chargingProfileId} schedule periods are not sorted by start period`
+ )
+ chargingSchedule.chargingSchedulePeriod.sort(chargingSchedulePeriodCompareFn)
}
// Check if the first schedule period startPeriod property is equal to 0
if (chargingSchedule.chargingSchedulePeriod[0].startPeriod !== 0) {
logger.error(
- `${logPrefix} ${moduleName}.getLimitFromChargingProfiles: Charging profile id ${chargingProfile.chargingProfileId} first schedule period start period ${chargingSchedule.chargingSchedulePeriod[0].startPeriod} is not equal to 0`,
- );
- continue;
+ `${logPrefix} ${moduleName}.getLimitFromChargingProfiles: Charging profile id ${chargingProfile.chargingProfileId} first schedule period start period ${chargingSchedule.chargingSchedulePeriod[0].startPeriod} is not equal to 0`
+ )
+ continue
}
// Handle only one schedule period
if (chargingSchedule.chargingSchedulePeriod.length === 1) {
const result: ChargingProfilesLimit = {
limit: chargingSchedule.chargingSchedulePeriod[0].limit,
- chargingProfile,
- };
- logger.debug(debugLogMsg, result);
- return result;
+ chargingProfile
+ }
+ logger.debug(debugLogMsg, result)
+ return result
}
- let previousChargingSchedulePeriod: ChargingSchedulePeriod | undefined;
+ let previousChargingSchedulePeriod: ChargingSchedulePeriod | undefined
// Search for the right schedule period
for (const [
index,
- chargingSchedulePeriod,
+ chargingSchedulePeriod
] of chargingSchedule.chargingSchedulePeriod.entries()) {
// Find the right schedule period
if (
isAfter(
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
addSeconds(chargingSchedule.startSchedule!, chargingSchedulePeriod.startPeriod),
- currentDate,
+ currentDate
)
) {
// Found the schedule period: previous is the correct one
const result: ChargingProfilesLimit = {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
limit: previousChargingSchedulePeriod!.limit,
- chargingProfile,
- };
- logger.debug(debugLogMsg, result);
- return result;
+ chargingProfile
+ }
+ logger.debug(debugLogMsg, result)
+ return result
}
// Keep a reference to previous one
- previousChargingSchedulePeriod = chargingSchedulePeriod;
+ previousChargingSchedulePeriod = chargingSchedulePeriod
// Handle the last schedule period within the charging profile duration
if (
index === chargingSchedule.chargingSchedulePeriod.length - 1 ||
(index < chargingSchedule.chargingSchedulePeriod.length - 1 &&
differenceInSeconds(
addSeconds(
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
chargingSchedule.startSchedule!,
- chargingSchedule.chargingSchedulePeriod[index + 1].startPeriod,
+ chargingSchedule.chargingSchedulePeriod[index + 1].startPeriod
),
- chargingSchedule.startSchedule!,
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ chargingSchedule.startSchedule!
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
) > chargingSchedule.duration!)
) {
const result: ChargingProfilesLimit = {
limit: previousChargingSchedulePeriod.limit,
- chargingProfile,
- };
- logger.debug(debugLogMsg, result);
- return result;
+ chargingProfile
+ }
+ logger.debug(debugLogMsg, result)
+ return result
}
}
}
}
}
-};
+}
export const prepareChargingProfileKind = (
connectorStatus: ConnectorStatus,
chargingProfile: ChargingProfile,
currentDate: Date,
- logPrefix: string,
+ logPrefix: string
): boolean => {
switch (chargingProfile.chargingProfileKind) {
case ChargingProfileKindType.RECURRING:
if (!canProceedRecurringChargingProfile(chargingProfile, logPrefix)) {
- return false;
+ return false
}
- prepareRecurringChargingProfile(chargingProfile, currentDate, logPrefix);
- break;
+ prepareRecurringChargingProfile(chargingProfile, currentDate, logPrefix)
+ break
case ChargingProfileKindType.RELATIVE:
if (!isNullOrUndefined(chargingProfile.chargingSchedule.startSchedule)) {
logger.warn(
- `${logPrefix} ${moduleName}.prepareChargingProfileKind: Relative charging profile id ${chargingProfile.chargingProfileId} has a startSchedule property defined. It will be ignored or used if the connector has a transaction started`,
- );
- delete chargingProfile.chargingSchedule.startSchedule;
+ `${logPrefix} ${moduleName}.prepareChargingProfileKind: Relative charging profile id ${chargingProfile.chargingProfileId} has a startSchedule property defined. It will be ignored or used if the connector has a transaction started`
+ )
+ delete chargingProfile.chargingSchedule.startSchedule
}
- if (connectorStatus?.transactionStarted) {
- chargingProfile.chargingSchedule.startSchedule = connectorStatus?.transactionStart;
+ if (connectorStatus?.transactionStarted === true) {
+ chargingProfile.chargingSchedule.startSchedule = connectorStatus?.transactionStart
}
// FIXME: Handle relative charging profile duration
- break;
+ break
}
- return true;
-};
+ return true
+}
export const canProceedChargingProfile = (
chargingProfile: ChargingProfile,
currentDate: Date,
- logPrefix: string,
+ logPrefix: string
): boolean => {
if (
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
(isValidTime(chargingProfile.validFrom) && isBefore(currentDate, chargingProfile.validFrom!)) ||
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
(isValidTime(chargingProfile.validTo) && isAfter(currentDate, chargingProfile.validTo!))
) {
logger.debug(
`${logPrefix} ${moduleName}.canProceedChargingProfile: Charging profile id ${
chargingProfile.chargingProfileId
- } is not valid for the current date ${currentDate.toISOString()}`,
- );
- return false;
+ } is not valid for the current date ${currentDate.toISOString()}`
+ )
+ return false
}
if (
isNullOrUndefined(chargingProfile.chargingSchedule.startSchedule) ||
isNullOrUndefined(chargingProfile.chargingSchedule.duration)
) {
logger.error(
- `${logPrefix} ${moduleName}.canProceedChargingProfile: Charging profile id ${chargingProfile.chargingProfileId} has no startSchedule or duration defined`,
- );
- return false;
+ `${logPrefix} ${moduleName}.canProceedChargingProfile: Charging profile id ${chargingProfile.chargingProfileId} has no startSchedule or duration defined`
+ )
+ return false
}
if (
!isNullOrUndefined(chargingProfile.chargingSchedule.startSchedule) &&
!isValidTime(chargingProfile.chargingSchedule.startSchedule)
) {
logger.error(
- `${logPrefix} ${moduleName}.canProceedChargingProfile: Charging profile id ${chargingProfile.chargingProfileId} has an invalid startSchedule date defined`,
- );
- return false;
+ `${logPrefix} ${moduleName}.canProceedChargingProfile: Charging profile id ${chargingProfile.chargingProfileId} has an invalid startSchedule date defined`
+ )
+ return false
}
if (
!isNullOrUndefined(chargingProfile.chargingSchedule.duration) &&
!Number.isSafeInteger(chargingProfile.chargingSchedule.duration)
) {
logger.error(
- `${logPrefix} ${moduleName}.canProceedChargingProfile: Charging profile id ${chargingProfile.chargingProfileId} has non integer duration defined`,
- );
- return false;
+ `${logPrefix} ${moduleName}.canProceedChargingProfile: Charging profile id ${chargingProfile.chargingProfileId} has non integer duration defined`
+ )
+ return false
}
- return true;
-};
+ return true
+}
const canProceedRecurringChargingProfile = (
chargingProfile: ChargingProfile,
- logPrefix: string,
+ logPrefix: string
): boolean => {
if (
chargingProfile.chargingProfileKind === ChargingProfileKindType.RECURRING &&
isNullOrUndefined(chargingProfile.recurrencyKind)
) {
logger.error(
- `${logPrefix} ${moduleName}.canProceedRecurringChargingProfile: Recurring charging profile id ${chargingProfile.chargingProfileId} has no recurrencyKind defined`,
- );
- return false;
+ `${logPrefix} ${moduleName}.canProceedRecurringChargingProfile: Recurring charging profile id ${chargingProfile.chargingProfileId} has no recurrencyKind defined`
+ )
+ return false
}
if (
chargingProfile.chargingProfileKind === ChargingProfileKindType.RECURRING &&
isNullOrUndefined(chargingProfile.chargingSchedule.startSchedule)
) {
logger.error(
- `${logPrefix} ${moduleName}.canProceedRecurringChargingProfile: Recurring charging profile id ${chargingProfile.chargingProfileId} has no startSchedule defined`,
- );
- return false;
+ `${logPrefix} ${moduleName}.canProceedRecurringChargingProfile: Recurring charging profile id ${chargingProfile.chargingProfileId} has no startSchedule defined`
+ )
+ return false
}
- return true;
-};
+ return true
+}
/**
* Adjust recurring charging profile startSchedule to the current recurrency time interval if needed
const prepareRecurringChargingProfile = (
chargingProfile: ChargingProfile,
currentDate: Date,
- logPrefix: string,
+ logPrefix: string
): boolean => {
- const chargingSchedule = chargingProfile.chargingSchedule;
- let recurringIntervalTranslated = false;
- let recurringInterval: Interval;
+ const chargingSchedule = chargingProfile.chargingSchedule
+ let recurringIntervalTranslated = false
+ let recurringInterval: Interval
switch (chargingProfile.recurrencyKind) {
case RecurrencyKindType.DAILY:
recurringInterval = {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
start: chargingSchedule.startSchedule!,
- end: addDays(chargingSchedule.startSchedule!, 1),
- };
- checkRecurringChargingProfileDuration(chargingProfile, recurringInterval, logPrefix);
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ end: addDays(chargingSchedule.startSchedule!, 1)
+ }
+ checkRecurringChargingProfileDuration(chargingProfile, recurringInterval, logPrefix)
if (
!isWithinInterval(currentDate, recurringInterval) &&
isBefore(recurringInterval.end, currentDate)
) {
chargingSchedule.startSchedule = addDays(
recurringInterval.start,
- differenceInDays(currentDate, recurringInterval.start),
- );
+ differenceInDays(currentDate, recurringInterval.start)
+ )
recurringInterval = {
start: chargingSchedule.startSchedule,
- end: addDays(chargingSchedule.startSchedule, 1),
- };
- recurringIntervalTranslated = true;
+ end: addDays(chargingSchedule.startSchedule, 1)
+ }
+ recurringIntervalTranslated = true
}
- break;
+ break
case RecurrencyKindType.WEEKLY:
recurringInterval = {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
start: chargingSchedule.startSchedule!,
- end: addWeeks(chargingSchedule.startSchedule!, 1),
- };
- checkRecurringChargingProfileDuration(chargingProfile, recurringInterval, logPrefix);
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ end: addWeeks(chargingSchedule.startSchedule!, 1)
+ }
+ checkRecurringChargingProfileDuration(chargingProfile, recurringInterval, logPrefix)
if (
!isWithinInterval(currentDate, recurringInterval) &&
isBefore(recurringInterval.end, currentDate)
) {
chargingSchedule.startSchedule = addWeeks(
recurringInterval.start,
- differenceInWeeks(currentDate, recurringInterval.start),
- );
+ differenceInWeeks(currentDate, recurringInterval.start)
+ )
recurringInterval = {
start: chargingSchedule.startSchedule,
- end: addWeeks(chargingSchedule.startSchedule, 1),
- };
- recurringIntervalTranslated = true;
+ end: addWeeks(chargingSchedule.startSchedule, 1)
+ }
+ recurringIntervalTranslated = true
}
- break;
+ break
default:
logger.error(
- `${logPrefix} ${moduleName}.prepareRecurringChargingProfile: Recurring ${chargingProfile.recurrencyKind} charging profile id ${chargingProfile.chargingProfileId} is not supported`,
- );
+ `${logPrefix} ${moduleName}.prepareRecurringChargingProfile: Recurring ${chargingProfile.recurrencyKind} charging profile id ${chargingProfile.chargingProfileId} is not supported`
+ )
}
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
if (recurringIntervalTranslated && !isWithinInterval(currentDate, recurringInterval!)) {
logger.error(
`${logPrefix} ${moduleName}.prepareRecurringChargingProfile: Recurring ${
chargingProfile.recurrencyKind
} charging profile id ${chargingProfile.chargingProfileId} recurrency time interval [${toDate(
- recurringInterval!.start,
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ recurringInterval!.start
).toISOString()}, ${toDate(
- recurringInterval!.end,
- ).toISOString()}] has not been properly translated to current date ${currentDate.toISOString()} `,
- );
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ recurringInterval!.end
+ ).toISOString()}] has not been properly translated to current date ${currentDate.toISOString()} `
+ )
}
- return recurringIntervalTranslated;
-};
+ return recurringIntervalTranslated
+}
const checkRecurringChargingProfileDuration = (
chargingProfile: ChargingProfile,
interval: Interval,
- logPrefix: string,
+ logPrefix: string
): void => {
if (isNullOrUndefined(chargingProfile.chargingSchedule.duration)) {
logger.warn(
chargingProfile.chargingProfileId
} duration is not defined, set it to the recurrency time interval duration ${differenceInSeconds(
interval.end,
- interval.start,
- )}`,
- );
- chargingProfile.chargingSchedule.duration = differenceInSeconds(interval.end, interval.start);
+ interval.start
+ )}`
+ )
+ chargingProfile.chargingSchedule.duration = differenceInSeconds(interval.end, interval.start)
} else if (
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
chargingProfile.chargingSchedule.duration! > differenceInSeconds(interval.end, interval.start)
) {
logger.warn(
chargingProfile.chargingSchedule.duration
} is greater than the recurrency time interval duration ${differenceInSeconds(
interval.end,
- interval.start,
- )}`,
- );
- chargingProfile.chargingSchedule.duration = differenceInSeconds(interval.end, interval.start);
+ interval.start
+ )}`
+ )
+ chargingProfile.chargingSchedule.duration = differenceInSeconds(interval.end, interval.start)
}
-};
+}
const getRandomSerialNumberSuffix = (params?: {
- randomBytesLength?: number;
- upperCase?: boolean;
+ randomBytesLength?: number
+ upperCase?: boolean
}): string => {
- const randomSerialNumberSuffix = randomBytes(params?.randomBytesLength ?? 16).toString('hex');
- if (params?.upperCase) {
- return randomSerialNumberSuffix.toUpperCase();
+ const randomSerialNumberSuffix = randomBytes(params?.randomBytesLength ?? 16).toString('hex')
+ if (params?.upperCase === true) {
+ return randomSerialNumberSuffix.toUpperCase()
}
- return randomSerialNumberSuffix;
-};
+ return randomSerialNumberSuffix
+}
-import { type FSWatcher, readFileSync } from 'node:fs';
+import { type FSWatcher, readFileSync } from 'node:fs'
-import type { ChargingStation } from './ChargingStation.js';
-import { getIdTagsFile } from './Helpers.js';
-import { FileType, IdTagDistribution } from '../types/index.js';
+import type { ChargingStation } from './ChargingStation.js'
+import { getIdTagsFile } from './Helpers.js'
+import { FileType, IdTagDistribution } from '../types/index.js'
import {
handleFileException,
isNotEmptyString,
logPrefix,
logger,
secureRandom,
- watchJsonFile,
-} from '../utils/index.js';
+ watchJsonFile
+} from '../utils/index.js'
interface IdTagsCacheValueType {
- idTags: string[];
- idTagsFileWatcher: FSWatcher | undefined;
+ idTags: string[]
+ idTagsFileWatcher: FSWatcher | undefined
}
export class IdTagsCache {
- private static instance: IdTagsCache | null = null;
- private readonly idTagsCaches: Map<string, IdTagsCacheValueType>;
- private readonly idTagsCachesAddressableIndexes: Map<string, number>;
+ private static instance: IdTagsCache | null = null
+ private readonly idTagsCaches: Map<string, IdTagsCacheValueType>
+ private readonly idTagsCachesAddressableIndexes: Map<string, number>
- private constructor() {
- this.idTagsCaches = new Map<string, IdTagsCacheValueType>();
- this.idTagsCachesAddressableIndexes = new Map<string, number>();
+ private constructor () {
+ this.idTagsCaches = new Map<string, IdTagsCacheValueType>()
+ this.idTagsCachesAddressableIndexes = new Map<string, number>()
}
- public static getInstance(): IdTagsCache {
+ public static getInstance (): IdTagsCache {
if (IdTagsCache.instance === null) {
- IdTagsCache.instance = new IdTagsCache();
+ IdTagsCache.instance = new IdTagsCache()
}
- return IdTagsCache.instance;
+ return IdTagsCache.instance
}
/**
* @param connectorId -
* @returns
*/
- public getIdTag(
+ public getIdTag (
distribution: IdTagDistribution,
chargingStation: ChargingStation,
- connectorId: number,
+ connectorId: number
): string {
- const hashId = chargingStation.stationInfo.hashId;
- const idTagsFile = getIdTagsFile(chargingStation.stationInfo)!;
+ const hashId = chargingStation.stationInfo.hashId
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ const idTagsFile = getIdTagsFile(chargingStation.stationInfo)!
switch (distribution) {
case IdTagDistribution.RANDOM:
- return this.getRandomIdTag(hashId, idTagsFile);
+ return this.getRandomIdTag(hashId, idTagsFile)
case IdTagDistribution.ROUND_ROBIN:
- return this.getRoundRobinIdTag(hashId, idTagsFile);
+ return this.getRoundRobinIdTag(hashId, idTagsFile)
case IdTagDistribution.CONNECTOR_AFFINITY:
- return this.getConnectorAffinityIdTag(chargingStation, connectorId);
+ return this.getConnectorAffinityIdTag(chargingStation, connectorId)
default:
- return this.getRoundRobinIdTag(hashId, idTagsFile);
+ return this.getRoundRobinIdTag(hashId, idTagsFile)
}
}
* @param file -
* @returns
*/
- public getIdTags(file: string): string[] | undefined {
- if (this.hasIdTagsCache(file) === false) {
- this.setIdTagsCache(file, this.getIdTagsFromFile(file));
+ public getIdTags (file: string): string[] | undefined {
+ if (!this.hasIdTagsCache(file)) {
+ this.setIdTagsCache(file, this.getIdTagsFromFile(file))
}
- return this.getIdTagsCache(file);
+ return this.getIdTagsCache(file)
}
- public deleteIdTags(file: string): boolean {
- return this.deleteIdTagsCache(file) && this.deleteIdTagsCacheIndexes(file);
+ public deleteIdTags (file: string): boolean {
+ return this.deleteIdTagsCache(file) && this.deleteIdTagsCacheIndexes(file)
}
- private getRandomIdTag(hashId: string, file: string): string {
- const idTags = this.getIdTags(file)!;
- const addressableKey = this.getIdTagsCacheIndexesAddressableKey(file, hashId);
+ private getRandomIdTag (hashId: string, file: string): string {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ const idTags = this.getIdTags(file)!
+ const addressableKey = this.getIdTagsCacheIndexesAddressableKey(file, hashId)
this.idTagsCachesAddressableIndexes.set(
addressableKey,
- Math.floor(secureRandom() * idTags.length),
- );
- return idTags[this.idTagsCachesAddressableIndexes.get(addressableKey)!];
+ Math.floor(secureRandom() * idTags.length)
+ )
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ return idTags[this.idTagsCachesAddressableIndexes.get(addressableKey)!]
}
- private getRoundRobinIdTag(hashId: string, file: string): string {
- const idTags = this.getIdTags(file)!;
- const addressableKey = this.getIdTagsCacheIndexesAddressableKey(file, hashId);
- const idTagIndex = this.idTagsCachesAddressableIndexes.get(addressableKey) ?? 0;
- const idTag = idTags[idTagIndex];
+ private getRoundRobinIdTag (hashId: string, file: string): string {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ const idTags = this.getIdTags(file)!
+ const addressableKey = this.getIdTagsCacheIndexesAddressableKey(file, hashId)
+ const idTagIndex = this.idTagsCachesAddressableIndexes.get(addressableKey) ?? 0
+ const idTag = idTags[idTagIndex]
this.idTagsCachesAddressableIndexes.set(
addressableKey,
- idTagIndex === idTags.length - 1 ? 0 : idTagIndex + 1,
- );
- return idTag;
+ idTagIndex === idTags.length - 1 ? 0 : idTagIndex + 1
+ )
+ return idTag
}
- private getConnectorAffinityIdTag(chargingStation: ChargingStation, connectorId: number): string {
- const file = getIdTagsFile(chargingStation.stationInfo)!;
- const idTags = this.getIdTags(file)!;
+ private getConnectorAffinityIdTag (chargingStation: ChargingStation, connectorId: number): string {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ const file = getIdTagsFile(chargingStation.stationInfo)!
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ const idTags = this.getIdTags(file)!
const addressableKey = this.getIdTagsCacheIndexesAddressableKey(
file,
- chargingStation.stationInfo.hashId,
- );
+ chargingStation.stationInfo.hashId
+ )
this.idTagsCachesAddressableIndexes.set(
addressableKey,
- (chargingStation.index - 1 + (connectorId - 1)) % idTags.length,
- );
- return idTags[this.idTagsCachesAddressableIndexes.get(addressableKey)!];
+ (chargingStation.index - 1 + (connectorId - 1)) % idTags.length
+ )
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ return idTags[this.idTagsCachesAddressableIndexes.get(addressableKey)!]
}
- private hasIdTagsCache(file: string): boolean {
- return this.idTagsCaches.has(file);
+ private hasIdTagsCache (file: string): boolean {
+ return this.idTagsCaches.has(file)
}
- private setIdTagsCache(file: string, idTags: string[]) {
+ private setIdTagsCache (file: string, idTags: string[]): Map<string, IdTagsCacheValueType> {
return this.idTagsCaches.set(file, {
idTags,
idTagsFileWatcher: watchJsonFile(
if (isNotEmptyString(filename) && event === 'change') {
try {
logger.debug(
- `${this.logPrefix(file)} ${FileType.Authorization} file have changed, reload`,
- );
- this.deleteIdTagsCache(file);
- this.deleteIdTagsCacheIndexes(file);
+ `${this.logPrefix(file)} ${FileType.Authorization} file have changed, reload`
+ )
+ this.deleteIdTagsCache(file)
+ this.deleteIdTagsCacheIndexes(file)
} catch (error) {
handleFileException(
file,
error as NodeJS.ErrnoException,
this.logPrefix(file),
{
- throwError: false,
- },
- );
+ throwError: false
+ }
+ )
}
}
- },
- ),
- });
+ }
+ )
+ })
}
- private getIdTagsCache(file: string): string[] | undefined {
- return this.idTagsCaches.get(file)?.idTags;
+ private getIdTagsCache (file: string): string[] | undefined {
+ return this.idTagsCaches.get(file)?.idTags
}
- private deleteIdTagsCache(file: string): boolean {
- this.idTagsCaches.get(file)?.idTagsFileWatcher?.close();
- return this.idTagsCaches.delete(file);
+ private deleteIdTagsCache (file: string): boolean {
+ this.idTagsCaches.get(file)?.idTagsFileWatcher?.close()
+ return this.idTagsCaches.delete(file)
}
- private deleteIdTagsCacheIndexes(file: string): boolean {
- const deleted: boolean[] = [];
+ private deleteIdTagsCacheIndexes (file: string): boolean {
+ const deleted: boolean[] = []
for (const [key] of this.idTagsCachesAddressableIndexes) {
if (key.startsWith(file)) {
- deleted.push(this.idTagsCachesAddressableIndexes.delete(key));
+ deleted.push(this.idTagsCachesAddressableIndexes.delete(key))
}
}
- return !deleted.some((value) => value === false);
+ return !deleted.some((value) => !value)
}
- private getIdTagsCacheIndexesAddressableKey(prefix: string, uid: string): string {
- return `${prefix}${uid}`;
+ private getIdTagsCacheIndexesAddressableKey (prefix: string, uid: string): string {
+ return `${prefix}${uid}`
}
- private getIdTagsFromFile(file: string): string[] {
+ private getIdTagsFromFile (file: string): string[] {
if (isNotEmptyString(file)) {
try {
- return JSON.parse(readFileSync(file, 'utf8')) as string[];
+ return JSON.parse(readFileSync(file, 'utf8')) as string[]
} catch (error) {
handleFileException(
file,
FileType.Authorization,
error as NodeJS.ErrnoException,
- this.logPrefix(file),
- );
+ this.logPrefix(file)
+ )
}
}
- return [];
+ return []
}
- private logPrefix = (file: string): string => {
- return logPrefix(` Id tags cache for id tags file '${file}' |`);
- };
+ private readonly logPrefix = (file: string): string => {
+ return logPrefix(` Id tags cache for id tags file '${file}' |`)
+ }
}
-import { LRUMapWithDelete as LRUCache } from 'mnemonist';
+import { LRUMapWithDelete as LRUCache } from 'mnemonist'
-import { Bootstrap } from './Bootstrap.js';
-import type { ChargingStationConfiguration, ChargingStationTemplate } from '../types/index.js';
+import { Bootstrap } from './Bootstrap.js'
+import type { ChargingStationConfiguration, ChargingStationTemplate } from '../types/index.js'
import {
isEmptyObject,
isNotEmptyArray,
isNotEmptyString,
- isNullOrUndefined,
-} from '../utils/index.js';
+ isNullOrUndefined
+} from '../utils/index.js'
enum CacheType {
chargingStationTemplate = 'chargingStationTemplate',
- chargingStationConfiguration = 'chargingStationConfiguration',
+ chargingStationConfiguration = 'chargingStationConfiguration'
}
-type CacheValueType = ChargingStationTemplate | ChargingStationConfiguration;
+type CacheValueType = ChargingStationTemplate | ChargingStationConfiguration
export class SharedLRUCache {
- private static instance: SharedLRUCache | null = null;
- private readonly lruCache: LRUCache<string, CacheValueType>;
+ private static instance: SharedLRUCache | null = null
+ private readonly lruCache: LRUCache<string, CacheValueType>
- private constructor() {
+ private constructor () {
this.lruCache = new LRUCache<string, CacheValueType>(
Bootstrap.getInstance().numberOfChargingStationTemplates +
- Bootstrap.getInstance().numberOfChargingStations,
- );
+ Bootstrap.getInstance().numberOfChargingStations
+ )
}
- public static getInstance(): SharedLRUCache {
+ public static getInstance (): SharedLRUCache {
if (SharedLRUCache.instance === null) {
- SharedLRUCache.instance = new SharedLRUCache();
+ SharedLRUCache.instance = new SharedLRUCache()
}
- return SharedLRUCache.instance;
+ return SharedLRUCache.instance
}
- public hasChargingStationConfiguration(chargingStationConfigurationHash: string): boolean {
- return this.has(this.getChargingStationConfigurationKey(chargingStationConfigurationHash));
+ public hasChargingStationConfiguration (chargingStationConfigurationHash: string): boolean {
+ return this.has(this.getChargingStationConfigurationKey(chargingStationConfigurationHash))
}
- public setChargingStationConfiguration(
- chargingStationConfiguration: ChargingStationConfiguration,
+ public setChargingStationConfiguration (
+ chargingStationConfiguration: ChargingStationConfiguration
): void {
if (this.isChargingStationConfigurationCacheable(chargingStationConfiguration)) {
this.set(
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.getChargingStationConfigurationKey(chargingStationConfiguration.configurationHash!),
- chargingStationConfiguration,
- );
+ chargingStationConfiguration
+ )
}
}
- public getChargingStationConfiguration(
- chargingStationConfigurationHash: string,
+ public getChargingStationConfiguration (
+ chargingStationConfigurationHash: string
): ChargingStationConfiguration {
return this.get(
- this.getChargingStationConfigurationKey(chargingStationConfigurationHash),
- ) as ChargingStationConfiguration;
+ this.getChargingStationConfigurationKey(chargingStationConfigurationHash)
+ ) as ChargingStationConfiguration
}
- public deleteChargingStationConfiguration(chargingStationConfigurationHash: string): void {
- this.delete(this.getChargingStationConfigurationKey(chargingStationConfigurationHash));
+ public deleteChargingStationConfiguration (chargingStationConfigurationHash: string): void {
+ this.delete(this.getChargingStationConfigurationKey(chargingStationConfigurationHash))
}
- public hasChargingStationTemplate(chargingStationTemplateHash: string): boolean {
- return this.has(this.getChargingStationTemplateKey(chargingStationTemplateHash));
+ public hasChargingStationTemplate (chargingStationTemplateHash: string): boolean {
+ return this.has(this.getChargingStationTemplateKey(chargingStationTemplateHash))
}
- public setChargingStationTemplate(chargingStationTemplate: ChargingStationTemplate): void {
+ public setChargingStationTemplate (chargingStationTemplate: ChargingStationTemplate): void {
this.set(
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.getChargingStationTemplateKey(chargingStationTemplate.templateHash!),
- chargingStationTemplate,
- );
+ chargingStationTemplate
+ )
}
- public getChargingStationTemplate(chargingStationTemplateHash: string): ChargingStationTemplate {
+ public getChargingStationTemplate (chargingStationTemplateHash: string): ChargingStationTemplate {
return this.get(
- this.getChargingStationTemplateKey(chargingStationTemplateHash),
- ) as ChargingStationTemplate;
+ this.getChargingStationTemplateKey(chargingStationTemplateHash)
+ ) as ChargingStationTemplate
}
- public deleteChargingStationTemplate(chargingStationTemplateHash: string): void {
- this.delete(this.getChargingStationTemplateKey(chargingStationTemplateHash));
+ public deleteChargingStationTemplate (chargingStationTemplateHash: string): void {
+ this.delete(this.getChargingStationTemplateKey(chargingStationTemplateHash))
}
- public clear(): void {
- this.lruCache.clear();
+ public clear (): void {
+ this.lruCache.clear()
}
- private getChargingStationConfigurationKey(hash: string): string {
- return `${CacheType.chargingStationConfiguration}${hash}`;
+ private getChargingStationConfigurationKey (hash: string): string {
+ return `${CacheType.chargingStationConfiguration}${hash}`
}
- private getChargingStationTemplateKey(hash: string): string {
- return `${CacheType.chargingStationTemplate}${hash}`;
+ private getChargingStationTemplateKey (hash: string): string {
+ return `${CacheType.chargingStationTemplate}${hash}`
}
- private has(key: string): boolean {
- return this.lruCache.has(key);
+ private has (key: string): boolean {
+ return this.lruCache.has(key)
}
- private get(key: string): CacheValueType | undefined {
- return this.lruCache.get(key);
+ private get (key: string): CacheValueType | undefined {
+ return this.lruCache.get(key)
}
- private set(key: string, value: CacheValueType): void {
- this.lruCache.set(key, value);
+ private set (key: string, value: CacheValueType): void {
+ this.lruCache.set(key, value)
}
- private delete(key: string): void {
- this.lruCache.delete(key);
+ private delete (key: string): void {
+ this.lruCache.delete(key)
}
- private isChargingStationConfigurationCacheable(
- chargingStationConfiguration: ChargingStationConfiguration,
+ private isChargingStationConfigurationCacheable (
+ chargingStationConfiguration: ChargingStationConfiguration
): boolean {
return (
- isNullOrUndefined(chargingStationConfiguration?.configurationKey) === false &&
- isNullOrUndefined(chargingStationConfiguration?.stationInfo) === false &&
- isNullOrUndefined(chargingStationConfiguration?.automaticTransactionGenerator) === false &&
- isNullOrUndefined(chargingStationConfiguration?.configurationHash) === false &&
- isNotEmptyArray(chargingStationConfiguration?.configurationKey) === true &&
- isEmptyObject(chargingStationConfiguration.stationInfo!) === false &&
- isEmptyObject(chargingStationConfiguration.automaticTransactionGenerator!) === false &&
- isNotEmptyString(chargingStationConfiguration?.configurationHash) === true
- );
+ !isNullOrUndefined(chargingStationConfiguration?.configurationKey) &&
+ !isNullOrUndefined(chargingStationConfiguration?.stationInfo) &&
+ !isNullOrUndefined(chargingStationConfiguration?.automaticTransactionGenerator) &&
+ !isNullOrUndefined(chargingStationConfiguration?.configurationHash) &&
+ isNotEmptyArray(chargingStationConfiguration?.configurationKey) &&
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ !isEmptyObject(chargingStationConfiguration.stationInfo!) &&
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ !isEmptyObject(chargingStationConfiguration.automaticTransactionGenerator!) &&
+ isNotEmptyString(chargingStationConfiguration?.configurationHash)
+ )
}
}
-import { secondsToMilliseconds } from 'date-fns';
+import { secondsToMilliseconds } from 'date-fns'
-import { WorkerBroadcastChannel } from './WorkerBroadcastChannel.js';
-import { BaseError, type OCPPError } from '../../exception/index.js';
+import { WorkerBroadcastChannel } from './WorkerBroadcastChannel.js'
+import { BaseError, type OCPPError } from '../../exception/index.js'
import {
AuthorizationStatus,
type AuthorizeRequest,
type StatusNotificationRequest,
type StatusNotificationResponse,
type StopTransactionRequest,
- type StopTransactionResponse,
-} from '../../types/index.js';
+ type StopTransactionResponse
+} from '../../types/index.js'
import {
Constants,
convertToInt,
isEmptyObject,
isNullOrUndefined,
- logger,
-} from '../../utils/index.js';
-import type { ChargingStation } from '../ChargingStation.js';
-import { getConfigurationKey } from '../ConfigurationKeyUtils.js';
-import { buildMeterValue } from '../ocpp/index.js';
+ logger
+} from '../../utils/index.js'
+import type { ChargingStation } from '../ChargingStation.js'
+import { getConfigurationKey } from '../ConfigurationKeyUtils.js'
+import { buildMeterValue } from '../ocpp/index.js'
-const moduleName = 'ChargingStationWorkerBroadcastChannel';
+const moduleName = 'ChargingStationWorkerBroadcastChannel'
type CommandResponse =
| EmptyObject
| AuthorizeResponse
| BootNotificationResponse
| HeartbeatResponse
- | DataTransferResponse;
+ | DataTransferResponse
type CommandHandler = (
- requestPayload?: BroadcastChannelRequestPayload,
-) => Promise<CommandResponse | void> | void;
+ requestPayload?: BroadcastChannelRequestPayload
+ // eslint-disable-next-line @typescript-eslint/no-invalid-void-type
+) => Promise<CommandResponse | void> | void
export class ChargingStationWorkerBroadcastChannel extends WorkerBroadcastChannel {
- private readonly commandHandlers: Map<BroadcastChannelProcedureName, CommandHandler>;
- private readonly chargingStation: ChargingStation;
+ private readonly commandHandlers: Map<BroadcastChannelProcedureName, CommandHandler>
+ private readonly chargingStation: ChargingStation
- constructor(chargingStation: ChargingStation) {
- super();
+ constructor (chargingStation: ChargingStation) {
+ super()
const requestParams: RequestParams = {
- throwError: true,
- };
+ throwError: true
+ }
this.commandHandlers = new Map<BroadcastChannelProcedureName, CommandHandler>([
- [BroadcastChannelProcedureName.START_CHARGING_STATION, () => this.chargingStation.start()],
+ [
+ BroadcastChannelProcedureName.START_CHARGING_STATION,
+ () => {
+ this.chargingStation.start()
+ }
+ ],
[
BroadcastChannelProcedureName.STOP_CHARGING_STATION,
- async () => this.chargingStation.stop(),
+ async () => {
+ await this.chargingStation.stop()
+ }
],
[
BroadcastChannelProcedureName.OPEN_CONNECTION,
- () => this.chargingStation.openWSConnection(),
+ () => {
+ this.chargingStation.openWSConnection()
+ }
],
[
BroadcastChannelProcedureName.CLOSE_CONNECTION,
- () => this.chargingStation.closeWSConnection(),
+ () => {
+ this.chargingStation.closeWSConnection()
+ }
],
[
BroadcastChannelProcedureName.START_AUTOMATIC_TRANSACTION_GENERATOR,
- (requestPayload?: BroadcastChannelRequestPayload) =>
- this.chargingStation.startAutomaticTransactionGenerator(requestPayload?.connectorIds),
+ (requestPayload?: BroadcastChannelRequestPayload) => {
+ this.chargingStation.startAutomaticTransactionGenerator(requestPayload?.connectorIds)
+ }
],
[
BroadcastChannelProcedureName.STOP_AUTOMATIC_TRANSACTION_GENERATOR,
- (requestPayload?: BroadcastChannelRequestPayload) =>
- this.chargingStation.stopAutomaticTransactionGenerator(requestPayload?.connectorIds),
+ (requestPayload?: BroadcastChannelRequestPayload) => {
+ this.chargingStation.stopAutomaticTransactionGenerator(requestPayload?.connectorIds)
+ }
],
[
BroadcastChannelProcedureName.SET_SUPERVISION_URL,
- (requestPayload?: BroadcastChannelRequestPayload) =>
- this.chargingStation.setSupervisionUrl(requestPayload?.url as string),
+ (requestPayload?: BroadcastChannelRequestPayload) => {
+ this.chargingStation.setSupervisionUrl(requestPayload?.url as string)
+ }
],
[
BroadcastChannelProcedureName.START_TRANSACTION,
async (requestPayload?: BroadcastChannelRequestPayload) =>
- this.chargingStation.ocppRequestService.requestHandler<
- StartTransactionRequest,
- StartTransactionResponse
- >(this.chargingStation, RequestCommand.START_TRANSACTION, requestPayload, requestParams),
+ await this.chargingStation.ocppRequestService.requestHandler<
+ StartTransactionRequest,
+ StartTransactionResponse
+ >(this.chargingStation, RequestCommand.START_TRANSACTION, requestPayload, requestParams)
],
[
BroadcastChannelProcedureName.STOP_TRANSACTION,
async (requestPayload?: BroadcastChannelRequestPayload) =>
- this.chargingStation.ocppRequestService.requestHandler<
- StopTransactionRequest,
- StartTransactionResponse
+ await this.chargingStation.ocppRequestService.requestHandler<
+ StopTransactionRequest,
+ StartTransactionResponse
>(
this.chargingStation,
RequestCommand.STOP_TRANSACTION,
{
meterStop: this.chargingStation.getEnergyActiveImportRegisterByTransactionId(
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
requestPayload!.transactionId!,
- true,
+ true
),
- ...requestPayload,
+ ...requestPayload
},
- requestParams,
- ),
+ requestParams
+ )
],
[
BroadcastChannelProcedureName.AUTHORIZE,
async (requestPayload?: BroadcastChannelRequestPayload) =>
- this.chargingStation.ocppRequestService.requestHandler<
- AuthorizeRequest,
- AuthorizeResponse
- >(this.chargingStation, RequestCommand.AUTHORIZE, requestPayload, requestParams),
+ await this.chargingStation.ocppRequestService.requestHandler<
+ AuthorizeRequest,
+ AuthorizeResponse
+ >(this.chargingStation, RequestCommand.AUTHORIZE, requestPayload, requestParams)
],
[
BroadcastChannelProcedureName.BOOT_NOTIFICATION,
async (requestPayload?: BroadcastChannelRequestPayload) => {
this.chargingStation.bootNotificationResponse =
await this.chargingStation.ocppRequestService.requestHandler<
- BootNotificationRequest,
- BootNotificationResponse
+ BootNotificationRequest,
+ BootNotificationResponse
>(
this.chargingStation,
RequestCommand.BOOT_NOTIFICATION,
{
...this.chargingStation.bootNotificationRequest,
- ...requestPayload,
+ ...requestPayload
},
{
skipBufferingOnError: true,
- throwError: true,
- },
- );
- return this.chargingStation.bootNotificationResponse;
- },
+ throwError: true
+ }
+ )
+ return this.chargingStation.bootNotificationResponse
+ }
],
[
BroadcastChannelProcedureName.STATUS_NOTIFICATION,
async (requestPayload?: BroadcastChannelRequestPayload) =>
- this.chargingStation.ocppRequestService.requestHandler<
- StatusNotificationRequest,
- StatusNotificationResponse
- >(
- this.chargingStation,
- RequestCommand.STATUS_NOTIFICATION,
- requestPayload,
- requestParams,
- ),
+ await this.chargingStation.ocppRequestService.requestHandler<
+ StatusNotificationRequest,
+ StatusNotificationResponse
+ >(this.chargingStation, RequestCommand.STATUS_NOTIFICATION, requestPayload, requestParams)
],
[
BroadcastChannelProcedureName.HEARTBEAT,
async (requestPayload?: BroadcastChannelRequestPayload) =>
- this.chargingStation.ocppRequestService.requestHandler<
- HeartbeatRequest,
- HeartbeatResponse
- >(this.chargingStation, RequestCommand.HEARTBEAT, requestPayload, requestParams),
+ await this.chargingStation.ocppRequestService.requestHandler<
+ HeartbeatRequest,
+ HeartbeatResponse
+ >(this.chargingStation, RequestCommand.HEARTBEAT, requestPayload, requestParams)
],
[
BroadcastChannelProcedureName.METER_VALUES,
async (requestPayload?: BroadcastChannelRequestPayload) => {
const configuredMeterValueSampleInterval = getConfigurationKey(
chargingStation,
- StandardParametersKey.MeterValueSampleInterval,
- );
- return this.chargingStation.ocppRequestService.requestHandler<
- MeterValuesRequest,
- MeterValuesResponse
+ StandardParametersKey.MeterValueSampleInterval
+ )
+ return await this.chargingStation.ocppRequestService.requestHandler<
+ MeterValuesRequest,
+ MeterValuesResponse
>(
this.chargingStation,
RequestCommand.METER_VALUES,
meterValue: [
buildMeterValue(
this.chargingStation,
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
requestPayload!.connectorId!,
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.chargingStation.getConnectorStatus(requestPayload!.connectorId!)!
.transactionId!,
configuredMeterValueSampleInterval !== undefined
? secondsToMilliseconds(convertToInt(configuredMeterValueSampleInterval.value))
- : Constants.DEFAULT_METER_VALUES_INTERVAL,
- ),
+ : Constants.DEFAULT_METER_VALUES_INTERVAL
+ )
],
- ...requestPayload,
+ ...requestPayload
},
- requestParams,
- );
- },
+ requestParams
+ )
+ }
],
[
BroadcastChannelProcedureName.DATA_TRANSFER,
async (requestPayload?: BroadcastChannelRequestPayload) =>
- this.chargingStation.ocppRequestService.requestHandler<
- DataTransferRequest,
- DataTransferResponse
- >(this.chargingStation, RequestCommand.DATA_TRANSFER, requestPayload, requestParams),
+ await this.chargingStation.ocppRequestService.requestHandler<
+ DataTransferRequest,
+ DataTransferResponse
+ >(this.chargingStation, RequestCommand.DATA_TRANSFER, requestPayload, requestParams)
],
[
BroadcastChannelProcedureName.DIAGNOSTICS_STATUS_NOTIFICATION,
async (requestPayload?: BroadcastChannelRequestPayload) =>
- this.chargingStation.ocppRequestService.requestHandler<
- DiagnosticsStatusNotificationRequest,
- DiagnosticsStatusNotificationResponse
+ await this.chargingStation.ocppRequestService.requestHandler<
+ DiagnosticsStatusNotificationRequest,
+ DiagnosticsStatusNotificationResponse
>(
this.chargingStation,
RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION,
requestPayload,
- requestParams,
- ),
+ requestParams
+ )
],
[
BroadcastChannelProcedureName.FIRMWARE_STATUS_NOTIFICATION,
async (requestPayload?: BroadcastChannelRequestPayload) =>
- this.chargingStation.ocppRequestService.requestHandler<
- FirmwareStatusNotificationRequest,
- FirmwareStatusNotificationResponse
+ await this.chargingStation.ocppRequestService.requestHandler<
+ FirmwareStatusNotificationRequest,
+ FirmwareStatusNotificationResponse
>(
this.chargingStation,
RequestCommand.FIRMWARE_STATUS_NOTIFICATION,
requestPayload,
- requestParams,
- ),
- ],
- ]);
- this.chargingStation = chargingStation;
- this.onmessage = this.requestHandler.bind(this) as (message: unknown) => void;
- this.onmessageerror = this.messageErrorHandler.bind(this) as (message: unknown) => void;
+ requestParams
+ )
+ ]
+ ])
+ this.chargingStation = chargingStation
+ this.onmessage = this.requestHandler.bind(this) as (message: unknown) => void
+ this.onmessageerror = this.messageErrorHandler.bind(this) as (message: unknown) => void
}
- private async requestHandler(messageEvent: MessageEvent): Promise<void> {
- const validatedMessageEvent = this.validateMessageEvent(messageEvent);
+ private async requestHandler (messageEvent: MessageEvent): Promise<void> {
+ const validatedMessageEvent = this.validateMessageEvent(messageEvent)
if (validatedMessageEvent === false) {
- return;
+ return
}
- if (this.isResponse(validatedMessageEvent.data) === true) {
- return;
+ if (this.isResponse(validatedMessageEvent.data)) {
+ return
}
- const [uuid, command, requestPayload] = validatedMessageEvent.data as BroadcastChannelRequest;
+ const [uuid, command, requestPayload] = validatedMessageEvent.data as BroadcastChannelRequest
if (
!isNullOrUndefined(requestPayload.hashIds) &&
requestPayload.hashIds?.includes(this.chargingStation.stationInfo.hashId) === false
) {
- return;
+ return
}
if (!isNullOrUndefined(requestPayload.hashId)) {
logger.error(
- `${this.chargingStation.logPrefix()} ${moduleName}.requestHandler: 'hashId' field usage in PDU is deprecated, use 'hashIds' array instead`,
- );
- return;
+ `${this.chargingStation.logPrefix()} ${moduleName}.requestHandler: 'hashId' field usage in PDU is deprecated, use 'hashIds' array instead`
+ )
+ return
}
- let responsePayload: BroadcastChannelResponsePayload | undefined;
- let commandResponse: CommandResponse | void | undefined;
+ let responsePayload: BroadcastChannelResponsePayload | undefined
+ let commandResponse: CommandResponse | undefined
try {
- commandResponse = await this.commandHandler(command, requestPayload);
- if (isNullOrUndefined(commandResponse) || isEmptyObject(commandResponse as CommandResponse)) {
+ commandResponse = await this.commandHandler(command, requestPayload)
+ if (isNullOrUndefined(commandResponse) || isEmptyObject(commandResponse)) {
responsePayload = {
hashId: this.chargingStation.stationInfo.hashId,
- status: ResponseStatus.SUCCESS,
- };
+ status: ResponseStatus.SUCCESS
+ }
} else {
responsePayload = this.commandResponseToResponsePayload(
command,
requestPayload,
- commandResponse as CommandResponse,
- );
+ commandResponse
+ )
}
} catch (error) {
logger.error(
`${this.chargingStation.logPrefix()} ${moduleName}.requestHandler: Handle request error:`,
- error,
- );
+ error
+ )
responsePayload = {
hashId: this.chargingStation.stationInfo.hashId,
status: ResponseStatus.FAILURE,
command,
requestPayload,
- commandResponse: commandResponse as CommandResponse,
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ commandResponse: commandResponse!,
errorMessage: (error as OCPPError).message,
errorStack: (error as OCPPError).stack,
- errorDetails: (error as OCPPError).details,
- };
+ errorDetails: (error as OCPPError).details
+ }
} finally {
- this.sendResponse([uuid, responsePayload!]);
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ this.sendResponse([uuid, responsePayload!])
}
}
- private messageErrorHandler(messageEvent: MessageEvent): void {
+ private messageErrorHandler (messageEvent: MessageEvent): void {
logger.error(
`${this.chargingStation.logPrefix()} ${moduleName}.messageErrorHandler: Error at handling message:`,
- messageEvent,
- );
+ messageEvent
+ )
}
- private async commandHandler(
+ private async commandHandler (
command: BroadcastChannelProcedureName,
- requestPayload: BroadcastChannelRequestPayload,
- ): Promise<CommandResponse | void> {
- if (this.commandHandlers.has(command) === true) {
- this.cleanRequestPayload(command, requestPayload);
- return this.commandHandlers.get(command)!(requestPayload);
+ requestPayload: BroadcastChannelRequestPayload
+ // eslint-disable-next-line @typescript-eslint/no-invalid-void-type
+ ): Promise<void | CommandResponse> {
+ if (this.commandHandlers.has(command)) {
+ this.cleanRequestPayload(command, requestPayload)
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ return await this.commandHandlers.get(command)!(requestPayload)
}
- throw new BaseError(`Unknown worker broadcast channel command: '${command}'`);
+ throw new BaseError(`Unknown worker broadcast channel command: '${command}'`)
}
- private cleanRequestPayload(
+ private cleanRequestPayload (
command: BroadcastChannelProcedureName,
- requestPayload: BroadcastChannelRequestPayload,
+ requestPayload: BroadcastChannelRequestPayload
): void {
- delete requestPayload.hashId;
- delete requestPayload.hashIds;
- [
+ delete requestPayload.hashId
+ delete requestPayload.hashIds
+ ![
BroadcastChannelProcedureName.START_AUTOMATIC_TRANSACTION_GENERATOR,
- BroadcastChannelProcedureName.STOP_AUTOMATIC_TRANSACTION_GENERATOR,
- ].includes(command) === false && delete requestPayload.connectorIds;
+ BroadcastChannelProcedureName.STOP_AUTOMATIC_TRANSACTION_GENERATOR
+ ].includes(command) && delete requestPayload.connectorIds
}
- private commandResponseToResponsePayload(
+ private commandResponseToResponsePayload (
command: BroadcastChannelProcedureName,
requestPayload: BroadcastChannelRequestPayload,
- commandResponse: CommandResponse,
+ commandResponse: CommandResponse
): BroadcastChannelResponsePayload {
- const responseStatus = this.commandResponseToResponseStatus(command, commandResponse);
+ const responseStatus = this.commandResponseToResponseStatus(command, commandResponse)
if (responseStatus === ResponseStatus.SUCCESS) {
return {
hashId: this.chargingStation.stationInfo.hashId,
- status: responseStatus,
- };
+ status: responseStatus
+ }
}
return {
hashId: this.chargingStation.stationInfo.hashId,
status: responseStatus,
command,
requestPayload,
- commandResponse,
- };
+ commandResponse
+ }
}
- private commandResponseToResponseStatus(
+ private commandResponseToResponseStatus (
command: BroadcastChannelProcedureName,
- commandResponse: CommandResponse,
+ commandResponse: CommandResponse
): ResponseStatus {
switch (command) {
case BroadcastChannelProcedureName.START_TRANSACTION:
| AuthorizeResponse
)?.idTagInfo?.status === AuthorizationStatus.ACCEPTED
) {
- return ResponseStatus.SUCCESS;
+ return ResponseStatus.SUCCESS
}
- return ResponseStatus.FAILURE;
+ return ResponseStatus.FAILURE
case BroadcastChannelProcedureName.BOOT_NOTIFICATION:
if (commandResponse?.status === RegistrationStatusEnumType.ACCEPTED) {
- return ResponseStatus.SUCCESS;
+ return ResponseStatus.SUCCESS
}
- return ResponseStatus.FAILURE;
+ return ResponseStatus.FAILURE
case BroadcastChannelProcedureName.DATA_TRANSFER:
if (commandResponse?.status === DataTransferStatus.ACCEPTED) {
- return ResponseStatus.SUCCESS;
+ return ResponseStatus.SUCCESS
}
- return ResponseStatus.FAILURE;
+ return ResponseStatus.FAILURE
case BroadcastChannelProcedureName.STATUS_NOTIFICATION:
case BroadcastChannelProcedureName.METER_VALUES:
- if (isEmptyObject(commandResponse) === true) {
- return ResponseStatus.SUCCESS;
+ if (isEmptyObject(commandResponse)) {
+ return ResponseStatus.SUCCESS
}
- return ResponseStatus.FAILURE;
+ return ResponseStatus.FAILURE
case BroadcastChannelProcedureName.HEARTBEAT:
if ('currentTime' in commandResponse) {
- return ResponseStatus.SUCCESS;
+ return ResponseStatus.SUCCESS
}
- return ResponseStatus.FAILURE;
+ return ResponseStatus.FAILURE
default:
- return ResponseStatus.FAILURE;
+ return ResponseStatus.FAILURE
}
}
}
-import { WorkerBroadcastChannel } from './WorkerBroadcastChannel.js';
+import { WorkerBroadcastChannel } from './WorkerBroadcastChannel.js'
import {
type BroadcastChannelResponse,
type BroadcastChannelResponsePayload,
type MessageEvent,
type ResponsePayload,
- ResponseStatus,
-} from '../../types/index.js';
-import { isNullOrUndefined, logger } from '../../utils/index.js';
-import type { AbstractUIService } from '../ui-server/ui-services/AbstractUIService.js';
+ ResponseStatus
+} from '../../types/index.js'
+import { isNullOrUndefined, logger } from '../../utils/index.js'
+import type { AbstractUIService } from '../ui-server/ui-services/AbstractUIService.js'
-const moduleName = 'UIServiceWorkerBroadcastChannel';
+const moduleName = 'UIServiceWorkerBroadcastChannel'
interface Responses {
- responsesExpected: number;
- responsesReceived: number;
- responses: BroadcastChannelResponsePayload[];
+ responsesExpected: number
+ responsesReceived: number
+ responses: BroadcastChannelResponsePayload[]
}
export class UIServiceWorkerBroadcastChannel extends WorkerBroadcastChannel {
- private readonly uiService: AbstractUIService;
- private readonly responses: Map<string, Responses>;
+ private readonly uiService: AbstractUIService
+ private readonly responses: Map<string, Responses>
- constructor(uiService: AbstractUIService) {
- super();
- this.uiService = uiService;
- this.onmessage = this.responseHandler.bind(this) as (message: unknown) => void;
- this.onmessageerror = this.messageErrorHandler.bind(this) as (message: unknown) => void;
- this.responses = new Map<string, Responses>();
+ constructor (uiService: AbstractUIService) {
+ super()
+ this.uiService = uiService
+ this.onmessage = this.responseHandler.bind(this) as (message: unknown) => void
+ this.onmessageerror = this.messageErrorHandler.bind(this) as (message: unknown) => void
+ this.responses = new Map<string, Responses>()
}
- private responseHandler(messageEvent: MessageEvent): void {
- const validatedMessageEvent = this.validateMessageEvent(messageEvent);
+ private responseHandler (messageEvent: MessageEvent): void {
+ const validatedMessageEvent = this.validateMessageEvent(messageEvent)
if (validatedMessageEvent === false) {
- return;
+ return
}
- if (this.isRequest(validatedMessageEvent.data) === true) {
- return;
+ if (this.isRequest(validatedMessageEvent.data)) {
+ return
}
- const [uuid, responsePayload] = validatedMessageEvent.data as BroadcastChannelResponse;
- if (this.responses.has(uuid) === false) {
+ const [uuid, responsePayload] = validatedMessageEvent.data as BroadcastChannelResponse
+ if (!this.responses.has(uuid)) {
this.responses.set(uuid, {
responsesExpected: this.uiService.getBroadcastChannelExpectedResponses(uuid),
responsesReceived: 1,
- responses: [responsePayload],
- });
+ responses: [responsePayload]
+ })
} else if (
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.responses.get(uuid)!.responsesReceived <= this.responses.get(uuid)!.responsesExpected
) {
- ++this.responses.get(uuid)!.responsesReceived;
- this.responses.get(uuid)?.responses.push(responsePayload);
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ ++this.responses.get(uuid)!.responsesReceived
+ this.responses.get(uuid)?.responses.push(responsePayload)
}
if (
this.responses.get(uuid)?.responsesReceived === this.responses.get(uuid)?.responsesExpected
) {
- this.uiService.sendResponse(uuid, this.buildResponsePayload(uuid));
- this.responses.delete(uuid);
- this.uiService.deleteBroadcastChannelRequest(uuid);
+ this.uiService.sendResponse(uuid, this.buildResponsePayload(uuid))
+ this.responses.delete(uuid)
+ this.uiService.deleteBroadcastChannelRequest(uuid)
}
}
- private buildResponsePayload(uuid: string): ResponsePayload {
+ private buildResponsePayload (uuid: string): ResponsePayload {
const responsesStatus =
this.responses
.get(uuid)
?.responses.every(({ status }) => status === ResponseStatus.SUCCESS) === true
? ResponseStatus.SUCCESS
- : ResponseStatus.FAILURE;
+ : ResponseStatus.FAILURE
return {
status: responsesStatus,
hashIdsSucceeded: this.responses
.get(uuid)
?.responses.map(({ status, hashId }) => {
if (hashId !== undefined && status === ResponseStatus.SUCCESS) {
- return hashId;
+ return hashId
}
+ return undefined
})
.filter((hashId) => !isNullOrUndefined(hashId)) as string[],
...(responsesStatus === ResponseStatus.FAILURE && {
.get(uuid)
?.responses.map(({ status, hashId }) => {
if (hashId !== undefined && status === ResponseStatus.FAILURE) {
- return hashId;
+ return hashId
}
+ return undefined
})
- .filter((hashId) => !isNullOrUndefined(hashId)) as string[],
+ .filter((hashId) => !isNullOrUndefined(hashId)) as string[]
}),
...(responsesStatus === ResponseStatus.FAILURE && {
responsesFailed: this.responses
.get(uuid)
?.responses.map((response) => {
if (response !== undefined && response.status === ResponseStatus.FAILURE) {
- return response;
+ return response
}
+ return undefined
})
- .filter((response) => !isNullOrUndefined(response)) as BroadcastChannelResponsePayload[],
- }),
- };
+ .filter((response) => !isNullOrUndefined(response)) as BroadcastChannelResponsePayload[]
+ })
+ }
}
- private messageErrorHandler(messageEvent: MessageEvent): void {
+ private messageErrorHandler (messageEvent: MessageEvent): void {
logger.error(
`${this.uiService.logPrefix(moduleName, 'messageErrorHandler')} Error at handling message:`,
- messageEvent,
- );
+ messageEvent
+ )
}
}
-import { BroadcastChannel } from 'node:worker_threads';
+import { BroadcastChannel } from 'node:worker_threads'
import type {
BroadcastChannelRequest,
BroadcastChannelResponse,
JsonType,
- MessageEvent,
-} from '../../types/index.js';
-import { logPrefix, logger, validateUUID } from '../../utils/index.js';
+ MessageEvent
+} from '../../types/index.js'
+import { logPrefix, logger, validateUUID } from '../../utils/index.js'
-const moduleName = 'WorkerBroadcastChannel';
+const moduleName = 'WorkerBroadcastChannel'
export abstract class WorkerBroadcastChannel extends BroadcastChannel {
- protected constructor() {
- super('worker');
+ protected constructor () {
+ super('worker')
}
- public sendRequest(request: BroadcastChannelRequest): void {
- this.postMessage(request);
+ public sendRequest (request: BroadcastChannelRequest): void {
+ this.postMessage(request)
}
- protected sendResponse(response: BroadcastChannelResponse): void {
- this.postMessage(response);
+ protected sendResponse (response: BroadcastChannelResponse): void {
+ this.postMessage(response)
}
- protected isRequest(message: JsonType[]): boolean {
- return Array.isArray(message) === true && message.length === 3;
+ protected isRequest (message: JsonType[]): boolean {
+ return Array.isArray(message) && message.length === 3
}
- protected isResponse(message: JsonType[]): boolean {
- return Array.isArray(message) === true && message.length === 2;
+ protected isResponse (message: JsonType[]): boolean {
+ return Array.isArray(message) && message.length === 2
}
- protected validateMessageEvent(messageEvent: MessageEvent): MessageEvent | false {
- if (Array.isArray(messageEvent.data) === false) {
+ protected validateMessageEvent (messageEvent: MessageEvent): MessageEvent | false {
+ if (!Array.isArray(messageEvent.data)) {
logger.error(
`${this.logPrefix(
moduleName,
- 'validateMessageEvent',
- )} Worker broadcast channel protocol message event data is not an array`,
- );
- return false;
+ 'validateMessageEvent'
+ )} Worker broadcast channel protocol message event data is not an array`
+ )
+ return false
}
- if (validateUUID(messageEvent.data[0]) === false) {
+ if (!validateUUID(messageEvent.data[0])) {
logger.error(
`${this.logPrefix(
moduleName,
- 'validateMessageEvent',
- )} Worker broadcast channel protocol message event data UUID field is invalid`,
- );
- return false;
+ 'validateMessageEvent'
+ )} Worker broadcast channel protocol message event data UUID field is invalid`
+ )
+ return false
}
- return messageEvent;
+ return messageEvent
}
- private logPrefix = (modName: string, methodName: string): string => {
- return logPrefix(` Worker Broadcast Channel | ${modName}.${methodName}:`);
- };
+ private readonly logPrefix = (modName: string, methodName: string): string => {
+ return logPrefix(` Worker Broadcast Channel | ${modName}.${methodName}:`)
+ }
}
-export { Bootstrap } from './Bootstrap.js';
-export type { ChargingStation } from './ChargingStation.js';
+export { Bootstrap } from './Bootstrap.js'
+export type { ChargingStation } from './ChargingStation.js'
export {
addConfigurationKey,
getConfigurationKey,
- setConfigurationKeyValue,
-} from './ConfigurationKeyUtils.js';
+ setConfigurationKeyValue
+} from './ConfigurationKeyUtils.js'
export {
canProceedChargingProfile,
checkChargingStation,
hasReservationExpired,
prepareChargingProfileKind,
removeExpiredReservations,
- resetConnectorStatus,
-} from './Helpers.js';
+ resetConnectorStatus
+} from './Helpers.js'
-import { type ConnectorStatusTransition, OCPP16ChargePointStatus } from '../../../types/index.js';
-import { OCPPConstants } from '../OCPPConstants.js';
+import { type ConnectorStatusTransition, OCPP16ChargePointStatus } from '../../../types/index.js'
+import { OCPPConstants } from '../OCPPConstants.js'
export class OCPP16Constants extends OCPPConstants {
static readonly ChargePointStatusChargingStationTransitions: Readonly<
- ConnectorStatusTransition[]
+ ConnectorStatusTransition[]
> = Object.freeze([
- { to: OCPP16ChargePointStatus.Available },
- // { from: OCPP16ChargePointStatus.Available, to: OCPP16ChargePointStatus.Available },
- { from: OCPP16ChargePointStatus.Available, to: OCPP16ChargePointStatus.Unavailable },
- { from: OCPP16ChargePointStatus.Available, to: OCPP16ChargePointStatus.Faulted },
- { to: OCPP16ChargePointStatus.Unavailable },
- { from: OCPP16ChargePointStatus.Unavailable, to: OCPP16ChargePointStatus.Available },
- // { from: OCPP16ChargePointStatus.Unavailable, to: OCPP16ChargePointStatus.Unavailable },
- { from: OCPP16ChargePointStatus.Unavailable, to: OCPP16ChargePointStatus.Faulted },
- { to: OCPP16ChargePointStatus.Faulted },
- { from: OCPP16ChargePointStatus.Faulted, to: OCPP16ChargePointStatus.Available },
- { from: OCPP16ChargePointStatus.Faulted, to: OCPP16ChargePointStatus.Unavailable },
+ { to: OCPP16ChargePointStatus.Available },
+ // { from: OCPP16ChargePointStatus.Available, to: OCPP16ChargePointStatus.Available },
+ { from: OCPP16ChargePointStatus.Available, to: OCPP16ChargePointStatus.Unavailable },
+ { from: OCPP16ChargePointStatus.Available, to: OCPP16ChargePointStatus.Faulted },
+ { to: OCPP16ChargePointStatus.Unavailable },
+ { from: OCPP16ChargePointStatus.Unavailable, to: OCPP16ChargePointStatus.Available },
+ // { from: OCPP16ChargePointStatus.Unavailable, to: OCPP16ChargePointStatus.Unavailable },
+ { from: OCPP16ChargePointStatus.Unavailable, to: OCPP16ChargePointStatus.Faulted },
+ { to: OCPP16ChargePointStatus.Faulted },
+ { from: OCPP16ChargePointStatus.Faulted, to: OCPP16ChargePointStatus.Available },
+ { from: OCPP16ChargePointStatus.Faulted, to: OCPP16ChargePointStatus.Unavailable }
// { from: OCPP16ChargePointStatus.Faulted, to: OCPP16ChargePointStatus.Faulted },
- ]);
+ ])
static readonly ChargePointStatusConnectorTransitions: Readonly<ConnectorStatusTransition[]> =
Object.freeze([
{ from: OCPP16ChargePointStatus.Faulted, to: OCPP16ChargePointStatus.SuspendedEVSE },
{ from: OCPP16ChargePointStatus.Faulted, to: OCPP16ChargePointStatus.Finishing },
{ from: OCPP16ChargePointStatus.Faulted, to: OCPP16ChargePointStatus.Reserved },
- { from: OCPP16ChargePointStatus.Faulted, to: OCPP16ChargePointStatus.Unavailable },
+ { from: OCPP16ChargePointStatus.Faulted, to: OCPP16ChargePointStatus.Unavailable }
// { from: OCPP16ChargePointStatus.Faulted, to: OCPP16ChargePointStatus.Faulted },
- ]);
+ ])
}
// Partial Copyright Jerome Benoit. 2021-2023. All Rights Reserved.
-import { createWriteStream, readdirSync } from 'node:fs';
-import { dirname, join, resolve } from 'node:path';
-import { URL, fileURLToPath } from 'node:url';
+import { createWriteStream, readdirSync } from 'node:fs'
+import { dirname, join, resolve } from 'node:path'
+import { URL, fileURLToPath } from 'node:url'
-import type { JSONSchemaType } from 'ajv';
-import { Client, type FTPResponse } from 'basic-ftp';
+import type { JSONSchemaType } from 'ajv'
+import { Client, type FTPResponse } from 'basic-ftp'
import {
type Interval,
addSeconds,
differenceInSeconds,
isDate,
- secondsToMilliseconds,
-} from 'date-fns';
-import { maxTime } from 'date-fns/constants';
-import { create } from 'tar';
+ secondsToMilliseconds
+} from 'date-fns'
+import { maxTime } from 'date-fns/constants'
+import { create } from 'tar'
-import { OCPP16Constants } from './OCPP16Constants.js';
-import { OCPP16ServiceUtils } from './OCPP16ServiceUtils.js';
+import { OCPP16Constants } from './OCPP16Constants.js'
+import { OCPP16ServiceUtils } from './OCPP16ServiceUtils.js'
import {
type ChargingStation,
canProceedChargingProfile,
getConnectorChargingProfiles,
prepareChargingProfileKind,
removeExpiredReservations,
- setConfigurationKeyValue,
-} from '../../../charging-station/index.js';
-import { OCPPError } from '../../../exception/index.js';
+ setConfigurationKeyValue
+} from '../../../charging-station/index.js'
+import { OCPPError } from '../../../exception/index.js'
import {
type ChangeConfigurationRequest,
type ChangeConfigurationResponse,
type SetChargingProfileRequest,
type SetChargingProfileResponse,
type UnlockConnectorRequest,
- type UnlockConnectorResponse,
-} from '../../../types/index.js';
+ type UnlockConnectorResponse
+} from '../../../types/index.js'
import {
Constants,
convertToDate,
isNullOrUndefined,
isUndefined,
logger,
- sleep,
-} from '../../../utils/index.js';
-import { OCPPIncomingRequestService } from '../OCPPIncomingRequestService.js';
+ sleep
+} from '../../../utils/index.js'
+import { OCPPIncomingRequestService } from '../OCPPIncomingRequestService.js'
-const moduleName = 'OCPP16IncomingRequestService';
+const moduleName = 'OCPP16IncomingRequestService'
export class OCPP16IncomingRequestService extends OCPPIncomingRequestService {
- protected jsonSchemas: Map<OCPP16IncomingRequestCommand, JSONSchemaType<JsonType>>;
- private incomingRequestHandlers: Map<OCPP16IncomingRequestCommand, IncomingRequestHandler>;
+ protected jsonSchemas: Map<OCPP16IncomingRequestCommand, JSONSchemaType<JsonType>>
+ private readonly incomingRequestHandlers: Map<
+ OCPP16IncomingRequestCommand,
+ IncomingRequestHandler
+ >
- public constructor() {
+ public constructor () {
// if (new.target?.name === moduleName) {
- // throw new TypeError(`Cannot construct ${new.target?.name} instances directly`);
+ // throw new TypeError(`Cannot construct ${new.target?.name} instances directly`)
// }
- super(OCPPVersion.VERSION_16);
+ super(OCPPVersion.VERSION_16)
this.incomingRequestHandlers = new Map<OCPP16IncomingRequestCommand, IncomingRequestHandler>([
[
OCPP16IncomingRequestCommand.RESET,
- this.handleRequestReset.bind(this) as unknown as IncomingRequestHandler,
+ this.handleRequestReset.bind(this) as unknown as IncomingRequestHandler
],
[
OCPP16IncomingRequestCommand.CLEAR_CACHE,
- this.handleRequestClearCache.bind(this) as IncomingRequestHandler,
+ this.handleRequestClearCache.bind(this) as IncomingRequestHandler
],
[
OCPP16IncomingRequestCommand.UNLOCK_CONNECTOR,
- this.handleRequestUnlockConnector.bind(this) as unknown as IncomingRequestHandler,
+ this.handleRequestUnlockConnector.bind(this) as unknown as IncomingRequestHandler
],
[
OCPP16IncomingRequestCommand.GET_CONFIGURATION,
- this.handleRequestGetConfiguration.bind(this) as IncomingRequestHandler,
+ this.handleRequestGetConfiguration.bind(this) as IncomingRequestHandler
],
[
OCPP16IncomingRequestCommand.CHANGE_CONFIGURATION,
- this.handleRequestChangeConfiguration.bind(this) as unknown as IncomingRequestHandler,
+ this.handleRequestChangeConfiguration.bind(this) as unknown as IncomingRequestHandler
],
[
OCPP16IncomingRequestCommand.GET_COMPOSITE_SCHEDULE,
- this.handleRequestGetCompositeSchedule.bind(this) as unknown as IncomingRequestHandler,
+ this.handleRequestGetCompositeSchedule.bind(this) as unknown as IncomingRequestHandler
],
[
OCPP16IncomingRequestCommand.SET_CHARGING_PROFILE,
- this.handleRequestSetChargingProfile.bind(this) as unknown as IncomingRequestHandler,
+ this.handleRequestSetChargingProfile.bind(this) as unknown as IncomingRequestHandler
],
[
OCPP16IncomingRequestCommand.CLEAR_CHARGING_PROFILE,
- this.handleRequestClearChargingProfile.bind(this) as IncomingRequestHandler,
+ this.handleRequestClearChargingProfile.bind(this) as IncomingRequestHandler
],
[
OCPP16IncomingRequestCommand.CHANGE_AVAILABILITY,
- this.handleRequestChangeAvailability.bind(this) as unknown as IncomingRequestHandler,
+ this.handleRequestChangeAvailability.bind(this) as unknown as IncomingRequestHandler
],
[
OCPP16IncomingRequestCommand.REMOTE_START_TRANSACTION,
- this.handleRequestRemoteStartTransaction.bind(this) as unknown as IncomingRequestHandler,
+ this.handleRequestRemoteStartTransaction.bind(this) as unknown as IncomingRequestHandler
],
[
OCPP16IncomingRequestCommand.REMOTE_STOP_TRANSACTION,
- this.handleRequestRemoteStopTransaction.bind(this) as unknown as IncomingRequestHandler,
+ this.handleRequestRemoteStopTransaction.bind(this) as unknown as IncomingRequestHandler
],
[
OCPP16IncomingRequestCommand.GET_DIAGNOSTICS,
- this.handleRequestGetDiagnostics.bind(this) as IncomingRequestHandler,
+ this.handleRequestGetDiagnostics.bind(this) as IncomingRequestHandler
],
[
OCPP16IncomingRequestCommand.TRIGGER_MESSAGE,
- this.handleRequestTriggerMessage.bind(this) as unknown as IncomingRequestHandler,
+ this.handleRequestTriggerMessage.bind(this) as unknown as IncomingRequestHandler
],
[
OCPP16IncomingRequestCommand.DATA_TRANSFER,
- this.handleRequestDataTransfer.bind(this) as unknown as IncomingRequestHandler,
+ this.handleRequestDataTransfer.bind(this) as unknown as IncomingRequestHandler
],
[
OCPP16IncomingRequestCommand.UPDATE_FIRMWARE,
- this.handleRequestUpdateFirmware.bind(this) as unknown as IncomingRequestHandler,
+ this.handleRequestUpdateFirmware.bind(this) as unknown as IncomingRequestHandler
],
[
OCPP16IncomingRequestCommand.RESERVE_NOW,
- this.handleRequestReserveNow.bind(this) as unknown as IncomingRequestHandler,
+ this.handleRequestReserveNow.bind(this) as unknown as IncomingRequestHandler
],
[
OCPP16IncomingRequestCommand.CANCEL_RESERVATION,
- this.handleRequestCancelReservation.bind(this) as unknown as IncomingRequestHandler,
- ],
- ]);
+ this.handleRequestCancelReservation.bind(this) as unknown as IncomingRequestHandler
+ ]
+ ])
this.jsonSchemas = new Map<OCPP16IncomingRequestCommand, JSONSchemaType<JsonType>>([
[
OCPP16IncomingRequestCommand.RESET,
OCPP16ServiceUtils.parseJsonSchemaFile<ResetRequest>(
'assets/json-schemas/ocpp/1.6/Reset.json',
moduleName,
- 'constructor',
- ),
+ 'constructor'
+ )
],
[
OCPP16IncomingRequestCommand.CLEAR_CACHE,
OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16ClearCacheRequest>(
'assets/json-schemas/ocpp/1.6/ClearCache.json',
moduleName,
- 'constructor',
- ),
+ 'constructor'
+ )
],
[
OCPP16IncomingRequestCommand.UNLOCK_CONNECTOR,
OCPP16ServiceUtils.parseJsonSchemaFile<UnlockConnectorRequest>(
'assets/json-schemas/ocpp/1.6/UnlockConnector.json',
moduleName,
- 'constructor',
- ),
+ 'constructor'
+ )
],
[
OCPP16IncomingRequestCommand.GET_CONFIGURATION,
OCPP16ServiceUtils.parseJsonSchemaFile<GetConfigurationRequest>(
'assets/json-schemas/ocpp/1.6/GetConfiguration.json',
moduleName,
- 'constructor',
- ),
+ 'constructor'
+ )
],
[
OCPP16IncomingRequestCommand.CHANGE_CONFIGURATION,
OCPP16ServiceUtils.parseJsonSchemaFile<ChangeConfigurationRequest>(
'assets/json-schemas/ocpp/1.6/ChangeConfiguration.json',
moduleName,
- 'constructor',
- ),
+ 'constructor'
+ )
],
[
OCPP16IncomingRequestCommand.GET_DIAGNOSTICS,
OCPP16ServiceUtils.parseJsonSchemaFile<GetDiagnosticsRequest>(
'assets/json-schemas/ocpp/1.6/GetDiagnostics.json',
moduleName,
- 'constructor',
- ),
+ 'constructor'
+ )
],
[
OCPP16IncomingRequestCommand.GET_COMPOSITE_SCHEDULE,
OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16GetCompositeScheduleRequest>(
'assets/json-schemas/ocpp/1.6/GetCompositeSchedule.json',
moduleName,
- 'constructor',
- ),
+ 'constructor'
+ )
],
[
OCPP16IncomingRequestCommand.SET_CHARGING_PROFILE,
OCPP16ServiceUtils.parseJsonSchemaFile<SetChargingProfileRequest>(
'assets/json-schemas/ocpp/1.6/SetChargingProfile.json',
moduleName,
- 'constructor',
- ),
+ 'constructor'
+ )
],
[
OCPP16IncomingRequestCommand.CLEAR_CHARGING_PROFILE,
OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16ClearChargingProfileRequest>(
'assets/json-schemas/ocpp/1.6/ClearChargingProfile.json',
moduleName,
- 'constructor',
- ),
+ 'constructor'
+ )
],
[
OCPP16IncomingRequestCommand.CHANGE_AVAILABILITY,
OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16ChangeAvailabilityRequest>(
'assets/json-schemas/ocpp/1.6/ChangeAvailability.json',
moduleName,
- 'constructor',
- ),
+ 'constructor'
+ )
],
[
OCPP16IncomingRequestCommand.REMOTE_START_TRANSACTION,
OCPP16ServiceUtils.parseJsonSchemaFile<RemoteStartTransactionRequest>(
'assets/json-schemas/ocpp/1.6/RemoteStartTransaction.json',
moduleName,
- 'constructor',
- ),
+ 'constructor'
+ )
],
[
OCPP16IncomingRequestCommand.REMOTE_STOP_TRANSACTION,
OCPP16ServiceUtils.parseJsonSchemaFile<RemoteStopTransactionRequest>(
'assets/json-schemas/ocpp/1.6/RemoteStopTransaction.json',
moduleName,
- 'constructor',
- ),
+ 'constructor'
+ )
],
[
OCPP16IncomingRequestCommand.TRIGGER_MESSAGE,
OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16TriggerMessageRequest>(
'assets/json-schemas/ocpp/1.6/TriggerMessage.json',
moduleName,
- 'constructor',
- ),
+ 'constructor'
+ )
],
[
OCPP16IncomingRequestCommand.DATA_TRANSFER,
OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16DataTransferRequest>(
'assets/json-schemas/ocpp/1.6/DataTransfer.json',
moduleName,
- 'constructor',
- ),
+ 'constructor'
+ )
],
[
OCPP16IncomingRequestCommand.UPDATE_FIRMWARE,
OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16UpdateFirmwareRequest>(
'assets/json-schemas/ocpp/1.6/UpdateFirmware.json',
moduleName,
- 'constructor',
- ),
+ 'constructor'
+ )
],
[
OCPP16IncomingRequestCommand.RESERVE_NOW,
OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16ReserveNowRequest>(
'assets/json-schemas/ocpp/1.6/ReserveNow.json',
moduleName,
- 'constructor',
- ),
+ 'constructor'
+ )
],
[
OCPP16IncomingRequestCommand.CANCEL_RESERVATION,
OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16CancelReservationRequest>(
'assets/json-schemas/ocpp/1.6/CancelReservation.json',
moduleName,
- 'constructor',
- ),
- ],
- ]);
+ 'constructor'
+ )
+ ]
+ ])
this.validatePayload = this.validatePayload.bind(this) as (
chargingStation: ChargingStation,
commandName: OCPP16IncomingRequestCommand,
- commandPayload: JsonType,
- ) => boolean;
+ commandPayload: JsonType
+ ) => boolean
}
public async incomingRequestHandler<ReqType extends JsonType, ResType extends JsonType>(
chargingStation: ChargingStation,
messageId: string,
commandName: OCPP16IncomingRequestCommand,
- commandPayload: ReqType,
+ commandPayload: ReqType
): Promise<void> {
- let response: ResType;
+ let response: ResType
if (
chargingStation.stationInfo?.ocppStrictCompliance === true &&
- chargingStation.inPendingState() === true &&
+ chargingStation.inPendingState() &&
(commandName === OCPP16IncomingRequestCommand.REMOTE_START_TRANSACTION ||
commandName === OCPP16IncomingRequestCommand.REMOTE_STOP_TRANSACTION)
) {
`${commandName} cannot be issued to handle request PDU ${JSON.stringify(
commandPayload,
undefined,
- 2,
+ 2
)} while the charging station is in pending state on the central server`,
commandName,
- commandPayload,
- );
+ commandPayload
+ )
}
if (
- chargingStation.isRegistered() === true ||
+ chargingStation.isRegistered() ||
(chargingStation.stationInfo?.ocppStrictCompliance === false &&
- chargingStation.inUnknownState() === true)
+ chargingStation.inUnknownState())
) {
if (
- this.incomingRequestHandlers.has(commandName) === true &&
- OCPP16ServiceUtils.isIncomingRequestCommandSupported(chargingStation, commandName) === true
+ this.incomingRequestHandlers.has(commandName) &&
+ OCPP16ServiceUtils.isIncomingRequestCommandSupported(chargingStation, commandName)
) {
try {
- this.validatePayload(chargingStation, commandName, commandPayload);
+ this.validatePayload(chargingStation, commandName, commandPayload)
// Call the method to build the response
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
response = (await this.incomingRequestHandlers.get(commandName)!(
chargingStation,
- commandPayload,
- )) as ResType;
+ commandPayload
+ )) as ResType
} catch (error) {
// Log
logger.error(
`${chargingStation.logPrefix()} ${moduleName}.incomingRequestHandler: Handle incoming request error:`,
- error,
- );
- throw error;
+ error
+ )
+ throw error
}
} else {
// Throw exception
`${commandName} is not implemented to handle request PDU ${JSON.stringify(
commandPayload,
undefined,
- 2,
+ 2
)}`,
commandName,
- commandPayload,
- );
+ commandPayload
+ )
}
} else {
throw new OCPPError(
`${commandName} cannot be issued to handle request PDU ${JSON.stringify(
commandPayload,
undefined,
- 2,
+ 2
)} while the charging station is not registered on the central server.`,
commandName,
- commandPayload,
- );
+ commandPayload
+ )
}
// Send the built response
await chargingStation.ocppRequestService.sendResponse(
chargingStation,
messageId,
response,
- commandName,
- );
+ commandName
+ )
}
- private validatePayload(
+ private validatePayload (
chargingStation: ChargingStation,
commandName: OCPP16IncomingRequestCommand,
- commandPayload: JsonType,
+ commandPayload: JsonType
): boolean {
- if (this.jsonSchemas.has(commandName) === true) {
+ if (this.jsonSchemas.has(commandName)) {
return this.validateIncomingRequestPayload(
chargingStation,
commandName,
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.jsonSchemas.get(commandName)!,
- commandPayload,
- );
+ commandPayload
+ )
}
logger.warn(
- `${chargingStation.logPrefix()} ${moduleName}.validatePayload: No JSON schema found for command '${commandName}' PDU validation`,
- );
- return false;
+ `${chargingStation.logPrefix()} ${moduleName}.validatePayload: No JSON schema found for command '${commandName}' PDU validation`
+ )
+ return false
}
// Simulate charging station restart
- private handleRequestReset(
+ private handleRequestReset (
chargingStation: ChargingStation,
- commandPayload: ResetRequest,
+ commandPayload: ResetRequest
): GenericResponse {
- const { type } = commandPayload;
+ const { type } = commandPayload
chargingStation
.reset(`${type}Reset` as OCPP16StopTransactionReason)
- .catch(Constants.EMPTY_FUNCTION);
+ .catch(Constants.EMPTY_FUNCTION)
logger.info(
`${chargingStation.logPrefix()} ${type} reset command received, simulating it. The station will be back online in ${formatDurationMilliSeconds(
- chargingStation.stationInfo.resetTime!,
- )}`,
- );
- return OCPP16Constants.OCPP_RESPONSE_ACCEPTED;
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ chargingStation.stationInfo.resetTime!
+ )}`
+ )
+ return OCPP16Constants.OCPP_RESPONSE_ACCEPTED
}
- private async handleRequestUnlockConnector(
+ private async handleRequestUnlockConnector (
chargingStation: ChargingStation,
- commandPayload: UnlockConnectorRequest,
+ commandPayload: UnlockConnectorRequest
): Promise<UnlockConnectorResponse> {
- const { connectorId } = commandPayload;
- if (chargingStation.hasConnector(connectorId) === false) {
+ const { connectorId } = commandPayload
+ if (!chargingStation.hasConnector(connectorId)) {
logger.error(
- `${chargingStation.logPrefix()} Trying to unlock a non existing connector id ${connectorId}`,
- );
- return OCPP16Constants.OCPP_RESPONSE_UNLOCK_NOT_SUPPORTED;
+ `${chargingStation.logPrefix()} Trying to unlock a non existing connector id ${connectorId}`
+ )
+ return OCPP16Constants.OCPP_RESPONSE_UNLOCK_NOT_SUPPORTED
}
if (connectorId === 0) {
- logger.error(`${chargingStation.logPrefix()} Trying to unlock connector id ${connectorId}`);
- return OCPP16Constants.OCPP_RESPONSE_UNLOCK_NOT_SUPPORTED;
+ logger.error(`${chargingStation.logPrefix()} Trying to unlock connector id ${connectorId}`)
+ return OCPP16Constants.OCPP_RESPONSE_UNLOCK_NOT_SUPPORTED
}
if (chargingStation.getConnectorStatus(connectorId)?.transactionStarted === true) {
const stopResponse = await chargingStation.stopTransactionOnConnector(
connectorId,
- OCPP16StopTransactionReason.UNLOCK_COMMAND,
- );
+ OCPP16StopTransactionReason.UNLOCK_COMMAND
+ )
if (stopResponse.idTagInfo?.status === OCPP16AuthorizationStatus.ACCEPTED) {
- return OCPP16Constants.OCPP_RESPONSE_UNLOCKED;
+ return OCPP16Constants.OCPP_RESPONSE_UNLOCKED
}
- return OCPP16Constants.OCPP_RESPONSE_UNLOCK_FAILED;
+ return OCPP16Constants.OCPP_RESPONSE_UNLOCK_FAILED
}
await OCPP16ServiceUtils.sendAndSetConnectorStatus(
chargingStation,
connectorId,
- OCPP16ChargePointStatus.Available,
- );
- return OCPP16Constants.OCPP_RESPONSE_UNLOCKED;
+ OCPP16ChargePointStatus.Available
+ )
+ return OCPP16Constants.OCPP_RESPONSE_UNLOCKED
}
- private handleRequestGetConfiguration(
+ private handleRequestGetConfiguration (
chargingStation: ChargingStation,
- commandPayload: GetConfigurationRequest,
+ commandPayload: GetConfigurationRequest
): GetConfigurationResponse {
- const { key } = commandPayload;
- const configurationKey: OCPPConfigurationKey[] = [];
- const unknownKey: string[] = [];
- if (isUndefined(key) === true) {
+ const { key } = commandPayload
+ const configurationKey: OCPPConfigurationKey[] = []
+ const unknownKey: string[] = []
+ if (isUndefined(key)) {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
for (const configuration of chargingStation.ocppConfiguration!.configurationKey!) {
- if (isUndefined(configuration.visible) === true) {
- configuration.visible = true;
+ if (isUndefined(configuration.visible)) {
+ configuration.visible = true
}
if (configuration.visible === false) {
- continue;
+ continue
}
configurationKey.push({
key: configuration.key,
readonly: configuration.readonly,
- value: configuration.value,
- });
+ value: configuration.value
+ })
}
- } else if (isNotEmptyArray(key) === true) {
+ } else if (isNotEmptyArray(key)) {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
for (const k of key!) {
- const keyFound = getConfigurationKey(chargingStation, k, true);
+ const keyFound = getConfigurationKey(chargingStation, k, true)
if (keyFound !== undefined) {
- if (isUndefined(keyFound.visible) === true) {
- keyFound.visible = true;
+ if (isUndefined(keyFound.visible)) {
+ keyFound.visible = true
}
if (keyFound.visible === false) {
- continue;
+ continue
}
configurationKey.push({
key: keyFound.key,
readonly: keyFound.readonly,
- value: keyFound.value,
- });
+ value: keyFound.value
+ })
} else {
- unknownKey.push(k);
+ unknownKey.push(k)
}
}
}
return {
configurationKey,
- unknownKey,
- };
+ unknownKey
+ }
}
- private handleRequestChangeConfiguration(
+ private handleRequestChangeConfiguration (
chargingStation: ChargingStation,
- commandPayload: ChangeConfigurationRequest,
+ commandPayload: ChangeConfigurationRequest
): ChangeConfigurationResponse {
- const { key, value } = commandPayload;
- const keyToChange = getConfigurationKey(chargingStation, key, true);
+ const { key, value } = commandPayload
+ const keyToChange = getConfigurationKey(chargingStation, key, true)
if (keyToChange?.readonly === true) {
- return OCPP16Constants.OCPP_CONFIGURATION_RESPONSE_REJECTED;
+ return OCPP16Constants.OCPP_CONFIGURATION_RESPONSE_REJECTED
} else if (keyToChange?.readonly === false) {
- let valueChanged = false;
+ let valueChanged = false
if (keyToChange.value !== value) {
- setConfigurationKeyValue(chargingStation, key, value, true);
- valueChanged = true;
+ setConfigurationKeyValue(chargingStation, key, value, true)
+ valueChanged = true
}
- let triggerHeartbeatRestart = false;
+ let triggerHeartbeatRestart = false
if (
(keyToChange.key as OCPP16StandardParametersKey) ===
OCPP16StandardParametersKey.HeartBeatInterval &&
setConfigurationKeyValue(
chargingStation,
OCPP16StandardParametersKey.HeartbeatInterval,
- value,
- );
- triggerHeartbeatRestart = true;
+ value
+ )
+ triggerHeartbeatRestart = true
}
if (
(keyToChange.key as OCPP16StandardParametersKey) ===
setConfigurationKeyValue(
chargingStation,
OCPP16StandardParametersKey.HeartBeatInterval,
- value,
- );
- triggerHeartbeatRestart = true;
+ value
+ )
+ triggerHeartbeatRestart = true
}
if (triggerHeartbeatRestart) {
- chargingStation.restartHeartbeat();
+ chargingStation.restartHeartbeat()
}
if (
(keyToChange.key as OCPP16StandardParametersKey) ===
OCPP16StandardParametersKey.WebSocketPingInterval &&
valueChanged
) {
- chargingStation.restartWebSocketPing();
+ chargingStation.restartWebSocketPing()
}
- if (keyToChange.reboot) {
- return OCPP16Constants.OCPP_CONFIGURATION_RESPONSE_REBOOT_REQUIRED;
+ if (keyToChange.reboot === true) {
+ return OCPP16Constants.OCPP_CONFIGURATION_RESPONSE_REBOOT_REQUIRED
}
- return OCPP16Constants.OCPP_CONFIGURATION_RESPONSE_ACCEPTED;
+ return OCPP16Constants.OCPP_CONFIGURATION_RESPONSE_ACCEPTED
}
- return OCPP16Constants.OCPP_CONFIGURATION_RESPONSE_NOT_SUPPORTED;
+ return OCPP16Constants.OCPP_CONFIGURATION_RESPONSE_NOT_SUPPORTED
}
- private handleRequestSetChargingProfile(
+ private handleRequestSetChargingProfile (
chargingStation: ChargingStation,
- commandPayload: SetChargingProfileRequest,
+ commandPayload: SetChargingProfileRequest
): SetChargingProfileResponse {
if (
- OCPP16ServiceUtils.checkFeatureProfile(
+ !OCPP16ServiceUtils.checkFeatureProfile(
chargingStation,
OCPP16SupportedFeatureProfiles.SmartCharging,
- OCPP16IncomingRequestCommand.SET_CHARGING_PROFILE,
- ) === false
+ OCPP16IncomingRequestCommand.SET_CHARGING_PROFILE
+ )
) {
- return OCPP16Constants.OCPP_SET_CHARGING_PROFILE_RESPONSE_NOT_SUPPORTED;
+ return OCPP16Constants.OCPP_SET_CHARGING_PROFILE_RESPONSE_NOT_SUPPORTED
}
- const { connectorId, csChargingProfiles } = commandPayload;
- if (chargingStation.hasConnector(connectorId) === false) {
+ const { connectorId, csChargingProfiles } = commandPayload
+ if (!chargingStation.hasConnector(connectorId)) {
logger.error(
- `${chargingStation.logPrefix()} Trying to set charging profile(s) to a non existing connector id ${connectorId}`,
- );
- return OCPP16Constants.OCPP_SET_CHARGING_PROFILE_RESPONSE_REJECTED;
+ `${chargingStation.logPrefix()} Trying to set charging profile(s) to a non existing connector id ${connectorId}`
+ )
+ return OCPP16Constants.OCPP_SET_CHARGING_PROFILE_RESPONSE_REJECTED
}
if (
csChargingProfiles.chargingProfilePurpose ===
OCPP16ChargingProfilePurposeType.CHARGE_POINT_MAX_PROFILE &&
connectorId !== 0
) {
- return OCPP16Constants.OCPP_SET_CHARGING_PROFILE_RESPONSE_REJECTED;
+ return OCPP16Constants.OCPP_SET_CHARGING_PROFILE_RESPONSE_REJECTED
}
if (
csChargingProfiles.chargingProfilePurpose === OCPP16ChargingProfilePurposeType.TX_PROFILE &&
connectorId === 0
) {
logger.error(
- `${chargingStation.logPrefix()} Trying to set transaction charging profile(s) on connector ${connectorId}`,
- );
- return OCPP16Constants.OCPP_SET_CHARGING_PROFILE_RESPONSE_REJECTED;
+ `${chargingStation.logPrefix()} Trying to set transaction charging profile(s) on connector ${connectorId}`
+ )
+ return OCPP16Constants.OCPP_SET_CHARGING_PROFILE_RESPONSE_REJECTED
}
- const connectorStatus = chargingStation.getConnectorStatus(connectorId);
+ const connectorStatus = chargingStation.getConnectorStatus(connectorId)
if (
csChargingProfiles.chargingProfilePurpose === OCPP16ChargingProfilePurposeType.TX_PROFILE &&
connectorId > 0 &&
connectorStatus?.transactionStarted === false
) {
logger.error(
- `${chargingStation.logPrefix()} Trying to set transaction charging profile(s) on connector ${connectorId} without a started transaction`,
- );
- return OCPP16Constants.OCPP_SET_CHARGING_PROFILE_RESPONSE_REJECTED;
+ `${chargingStation.logPrefix()} Trying to set transaction charging profile(s) on connector ${connectorId} without a started transaction`
+ )
+ return OCPP16Constants.OCPP_SET_CHARGING_PROFILE_RESPONSE_REJECTED
}
if (
csChargingProfiles.chargingProfilePurpose === OCPP16ChargingProfilePurposeType.TX_PROFILE &&
logger.error(
`${chargingStation.logPrefix()} Trying to set transaction charging profile(s) on connector ${connectorId} with a different transaction id ${
csChargingProfiles.transactionId
- } than the started transaction id ${connectorStatus?.transactionId}`,
- );
- return OCPP16Constants.OCPP_SET_CHARGING_PROFILE_RESPONSE_REJECTED;
+ } than the started transaction id ${connectorStatus?.transactionId}`
+ )
+ return OCPP16Constants.OCPP_SET_CHARGING_PROFILE_RESPONSE_REJECTED
}
- OCPP16ServiceUtils.setChargingProfile(chargingStation, connectorId, csChargingProfiles);
+ OCPP16ServiceUtils.setChargingProfile(chargingStation, connectorId, csChargingProfiles)
logger.debug(
`${chargingStation.logPrefix()} Charging profile(s) set on connector id ${connectorId}: %j`,
- csChargingProfiles,
- );
- return OCPP16Constants.OCPP_SET_CHARGING_PROFILE_RESPONSE_ACCEPTED;
+ csChargingProfiles
+ )
+ return OCPP16Constants.OCPP_SET_CHARGING_PROFILE_RESPONSE_ACCEPTED
}
- private handleRequestGetCompositeSchedule(
+ private handleRequestGetCompositeSchedule (
chargingStation: ChargingStation,
- commandPayload: OCPP16GetCompositeScheduleRequest,
+ commandPayload: OCPP16GetCompositeScheduleRequest
): OCPP16GetCompositeScheduleResponse {
if (
- OCPP16ServiceUtils.checkFeatureProfile(
+ !OCPP16ServiceUtils.checkFeatureProfile(
chargingStation,
OCPP16SupportedFeatureProfiles.SmartCharging,
- OCPP16IncomingRequestCommand.GET_COMPOSITE_SCHEDULE,
- ) === false
+ OCPP16IncomingRequestCommand.GET_COMPOSITE_SCHEDULE
+ )
) {
- return OCPP16Constants.OCPP_RESPONSE_REJECTED;
+ return OCPP16Constants.OCPP_RESPONSE_REJECTED
}
- const { connectorId, duration, chargingRateUnit } = commandPayload;
- if (chargingStation.hasConnector(connectorId) === false) {
+ const { connectorId, duration, chargingRateUnit } = commandPayload
+ if (!chargingStation.hasConnector(connectorId)) {
logger.error(
- `${chargingStation.logPrefix()} Trying to get composite schedule to a non existing connector id ${connectorId}`,
- );
- return OCPP16Constants.OCPP_RESPONSE_REJECTED;
+ `${chargingStation.logPrefix()} Trying to get composite schedule to a non existing connector id ${connectorId}`
+ )
+ return OCPP16Constants.OCPP_RESPONSE_REJECTED
}
if (connectorId === 0) {
logger.error(
- `${chargingStation.logPrefix()} Get composite schedule on connector id ${connectorId} is not yet supported`,
- );
- return OCPP16Constants.OCPP_RESPONSE_REJECTED;
+ `${chargingStation.logPrefix()} Get composite schedule on connector id ${connectorId} is not yet supported`
+ )
+ return OCPP16Constants.OCPP_RESPONSE_REJECTED
}
- if (chargingRateUnit) {
+ if (chargingRateUnit != null) {
logger.warn(
- `${chargingStation.logPrefix()} Get composite schedule with a specified rate unit is not yet supported, no conversion will be done`,
- );
+ `${chargingStation.logPrefix()} Get composite schedule with a specified rate unit is not yet supported, no conversion will be done`
+ )
}
- const connectorStatus = chargingStation.getConnectorStatus(connectorId)!;
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ const connectorStatus = chargingStation.getConnectorStatus(connectorId)!
if (
isEmptyArray(
- connectorStatus?.chargingProfiles &&
- isEmptyArray(chargingStation.getConnectorStatus(0)?.chargingProfiles),
+ connectorStatus?.chargingProfiles != null &&
+ isEmptyArray(chargingStation.getConnectorStatus(0)?.chargingProfiles)
)
) {
- return OCPP16Constants.OCPP_RESPONSE_REJECTED;
+ return OCPP16Constants.OCPP_RESPONSE_REJECTED
}
- const currentDate = new Date();
+ const currentDate = new Date()
const compositeScheduleInterval: Interval = {
start: currentDate,
- end: addSeconds(currentDate, duration),
- };
+ end: addSeconds(currentDate, duration)
+ }
// Get charging profiles sorted by connector id then stack level
const chargingProfiles: OCPP16ChargingProfile[] = getConnectorChargingProfiles(
chargingStation,
- connectorId,
- );
- let previousCompositeSchedule: OCPP16ChargingSchedule | undefined;
- let compositeSchedule: OCPP16ChargingSchedule | undefined;
+ connectorId
+ )
+ let previousCompositeSchedule: OCPP16ChargingSchedule | undefined
+ let compositeSchedule: OCPP16ChargingSchedule | undefined
for (const chargingProfile of chargingProfiles) {
if (
isNullOrUndefined(chargingProfile.chargingSchedule?.startSchedule) &&
- connectorStatus?.transactionStarted
+ connectorStatus?.transactionStarted === true
) {
logger.debug(
`${chargingStation.logPrefix()} ${moduleName}.handleRequestGetCompositeSchedule: Charging profile id ${
chargingProfile.chargingProfileId
- } has no startSchedule defined. Trying to set it to the connector current transaction start date`,
- );
+ } has no startSchedule defined. Trying to set it to the connector current transaction start date`
+ )
// OCPP specifies that if startSchedule is not defined, it should be relative to start of the connector transaction
- chargingProfile.chargingSchedule.startSchedule = connectorStatus?.transactionStart;
+ chargingProfile.chargingSchedule.startSchedule = connectorStatus?.transactionStart
}
if (
!isNullOrUndefined(chargingProfile.chargingSchedule?.startSchedule) &&
logger.warn(
`${chargingStation.logPrefix()} ${moduleName}.handleRequestGetCompositeSchedule: Charging profile id ${
chargingProfile.chargingProfileId
- } startSchedule property is not a Date instance. Trying to convert it to a Date instance`,
- );
+ } startSchedule property is not a Date instance. Trying to convert it to a Date instance`
+ )
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
chargingProfile.chargingSchedule.startSchedule = convertToDate(
- chargingProfile.chargingSchedule?.startSchedule,
- )!;
+ chargingProfile.chargingSchedule?.startSchedule
+ )!
}
if (
!isNullOrUndefined(chargingProfile.chargingSchedule?.startSchedule) &&
logger.debug(
`${chargingStation.logPrefix()} ${moduleName}.handleRequestGetCompositeSchedule: Charging profile id ${
chargingProfile.chargingProfileId
- } has no duration defined and will be set to the maximum time allowed`,
- );
+ } has no duration defined and will be set to the maximum time allowed`
+ )
// OCPP specifies that if duration is not defined, it should be infinite
chargingProfile.chargingSchedule.duration = differenceInSeconds(
maxTime,
- chargingProfile.chargingSchedule.startSchedule!,
- );
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ chargingProfile.chargingSchedule.startSchedule!
+ )
}
if (
!prepareChargingProfileKind(
connectorStatus,
chargingProfile,
compositeScheduleInterval.start as Date,
- chargingStation.logPrefix(),
+ chargingStation.logPrefix()
)
) {
- continue;
+ continue
}
if (
!canProceedChargingProfile(
chargingProfile,
compositeScheduleInterval.start as Date,
- chargingStation.logPrefix(),
+ chargingStation.logPrefix()
)
) {
- continue;
+ continue
}
compositeSchedule = OCPP16ServiceUtils.composeChargingSchedules(
previousCompositeSchedule,
chargingProfile.chargingSchedule,
- compositeScheduleInterval,
- );
- previousCompositeSchedule = compositeSchedule;
+ compositeScheduleInterval
+ )
+ previousCompositeSchedule = compositeSchedule
}
- if (compositeSchedule) {
+ if (compositeSchedule != null) {
return {
status: GenericStatus.Accepted,
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
scheduleStart: compositeSchedule.startSchedule!,
connectorId,
- chargingSchedule: compositeSchedule,
- };
+ chargingSchedule: compositeSchedule
+ }
}
- return OCPP16Constants.OCPP_RESPONSE_REJECTED;
+ return OCPP16Constants.OCPP_RESPONSE_REJECTED
}
- private handleRequestClearChargingProfile(
+ private handleRequestClearChargingProfile (
chargingStation: ChargingStation,
- commandPayload: OCPP16ClearChargingProfileRequest,
+ commandPayload: OCPP16ClearChargingProfileRequest
): OCPP16ClearChargingProfileResponse {
if (
- OCPP16ServiceUtils.checkFeatureProfile(
+ !OCPP16ServiceUtils.checkFeatureProfile(
chargingStation,
OCPP16SupportedFeatureProfiles.SmartCharging,
- OCPP16IncomingRequestCommand.CLEAR_CHARGING_PROFILE,
- ) === false
+ OCPP16IncomingRequestCommand.CLEAR_CHARGING_PROFILE
+ )
) {
- return OCPP16Constants.OCPP_CLEAR_CHARGING_PROFILE_RESPONSE_UNKNOWN;
+ return OCPP16Constants.OCPP_CLEAR_CHARGING_PROFILE_RESPONSE_UNKNOWN
}
- const { connectorId } = commandPayload;
- if (chargingStation.hasConnector(connectorId!) === false) {
+ const { connectorId } = commandPayload
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ if (!chargingStation.hasConnector(connectorId!)) {
logger.error(
- `${chargingStation.logPrefix()} Trying to clear a charging profile(s) to a non existing connector id ${connectorId}`,
- );
- return OCPP16Constants.OCPP_CLEAR_CHARGING_PROFILE_RESPONSE_UNKNOWN;
+ `${chargingStation.logPrefix()} Trying to clear a charging profile(s) to a non existing connector id ${connectorId}`
+ )
+ return OCPP16Constants.OCPP_CLEAR_CHARGING_PROFILE_RESPONSE_UNKNOWN
}
- const connectorStatus = chargingStation.getConnectorStatus(connectorId!);
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ const connectorStatus = chargingStation.getConnectorStatus(connectorId!)
if (!isNullOrUndefined(connectorId) && isNotEmptyArray(connectorStatus?.chargingProfiles)) {
- connectorStatus!.chargingProfiles = [];
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ connectorStatus!.chargingProfiles = []
logger.debug(
- `${chargingStation.logPrefix()} Charging profile(s) cleared on connector id ${connectorId}`,
- );
- return OCPP16Constants.OCPP_CLEAR_CHARGING_PROFILE_RESPONSE_ACCEPTED;
+ `${chargingStation.logPrefix()} Charging profile(s) cleared on connector id ${connectorId}`
+ )
+ return OCPP16Constants.OCPP_CLEAR_CHARGING_PROFILE_RESPONSE_ACCEPTED
}
if (isNullOrUndefined(connectorId)) {
- let clearedCP = false;
+ let clearedCP = false
if (chargingStation.hasEvses) {
for (const evseStatus of chargingStation.evses.values()) {
for (const status of evseStatus.connectors.values()) {
clearedCP = OCPP16ServiceUtils.clearChargingProfiles(
chargingStation,
commandPayload,
- status.chargingProfiles,
- );
+ status.chargingProfiles
+ )
}
}
} else {
clearedCP = OCPP16ServiceUtils.clearChargingProfiles(
chargingStation,
commandPayload,
- chargingStation.getConnectorStatus(id)?.chargingProfiles,
- );
+ chargingStation.getConnectorStatus(id)?.chargingProfiles
+ )
}
}
if (clearedCP) {
- return OCPP16Constants.OCPP_CLEAR_CHARGING_PROFILE_RESPONSE_ACCEPTED;
+ return OCPP16Constants.OCPP_CLEAR_CHARGING_PROFILE_RESPONSE_ACCEPTED
}
}
- return OCPP16Constants.OCPP_CLEAR_CHARGING_PROFILE_RESPONSE_UNKNOWN;
+ return OCPP16Constants.OCPP_CLEAR_CHARGING_PROFILE_RESPONSE_UNKNOWN
}
- private async handleRequestChangeAvailability(
+ private async handleRequestChangeAvailability (
chargingStation: ChargingStation,
- commandPayload: OCPP16ChangeAvailabilityRequest,
+ commandPayload: OCPP16ChangeAvailabilityRequest
): Promise<OCPP16ChangeAvailabilityResponse> {
- const { connectorId, type } = commandPayload;
- if (chargingStation.hasConnector(connectorId) === false) {
+ const { connectorId, type } = commandPayload
+ if (!chargingStation.hasConnector(connectorId)) {
logger.error(
- `${chargingStation.logPrefix()} Trying to change the availability of a non existing connector id ${connectorId}`,
- );
- return OCPP16Constants.OCPP_AVAILABILITY_RESPONSE_REJECTED;
+ `${chargingStation.logPrefix()} Trying to change the availability of a non existing connector id ${connectorId}`
+ )
+ return OCPP16Constants.OCPP_AVAILABILITY_RESPONSE_REJECTED
}
const chargePointStatus: OCPP16ChargePointStatus =
type === OCPP16AvailabilityType.Operative
? OCPP16ChargePointStatus.Available
- : OCPP16ChargePointStatus.Unavailable;
+ : OCPP16ChargePointStatus.Unavailable
if (connectorId === 0) {
- let response: OCPP16ChangeAvailabilityResponse;
+ let response: OCPP16ChangeAvailabilityResponse
if (chargingStation.hasEvses) {
for (const evseStatus of chargingStation.evses.values()) {
response = await OCPP16ServiceUtils.changeAvailability(
chargingStation,
[...evseStatus.connectors.keys()],
chargePointStatus,
- type,
- );
+ type
+ )
}
} else {
response = await OCPP16ServiceUtils.changeAvailability(
chargingStation,
[...chargingStation.connectors.keys()],
chargePointStatus,
- type,
- );
+ type
+ )
}
- return response!;
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ return response!
} else if (
connectorId > 0 &&
- (chargingStation.isChargingStationAvailable() === true ||
- (chargingStation.isChargingStationAvailable() === false &&
+ (chargingStation.isChargingStationAvailable() ||
+ (!chargingStation.isChargingStationAvailable() &&
type === OCPP16AvailabilityType.Inoperative))
) {
if (chargingStation.getConnectorStatus(connectorId)?.transactionStarted === true) {
- chargingStation.getConnectorStatus(connectorId)!.availability = type;
- return OCPP16Constants.OCPP_AVAILABILITY_RESPONSE_SCHEDULED;
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ chargingStation.getConnectorStatus(connectorId)!.availability = type
+ return OCPP16Constants.OCPP_AVAILABILITY_RESPONSE_SCHEDULED
}
- chargingStation.getConnectorStatus(connectorId)!.availability = type;
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ chargingStation.getConnectorStatus(connectorId)!.availability = type
await OCPP16ServiceUtils.sendAndSetConnectorStatus(
chargingStation,
connectorId,
- chargePointStatus,
- );
- return OCPP16Constants.OCPP_AVAILABILITY_RESPONSE_ACCEPTED;
+ chargePointStatus
+ )
+ return OCPP16Constants.OCPP_AVAILABILITY_RESPONSE_ACCEPTED
}
- return OCPP16Constants.OCPP_AVAILABILITY_RESPONSE_REJECTED;
+ return OCPP16Constants.OCPP_AVAILABILITY_RESPONSE_REJECTED
}
- private async handleRequestRemoteStartTransaction(
+ private async handleRequestRemoteStartTransaction (
chargingStation: ChargingStation,
- commandPayload: RemoteStartTransactionRequest,
+ commandPayload: RemoteStartTransactionRequest
): Promise<GenericResponse> {
- const { connectorId: transactionConnectorId, idTag, chargingProfile } = commandPayload;
- if (chargingStation.hasConnector(transactionConnectorId) === false) {
- return this.notifyRemoteStartTransactionRejected(
+ const { connectorId: transactionConnectorId, idTag, chargingProfile } = commandPayload
+ if (!chargingStation.hasConnector(transactionConnectorId)) {
+ return await this.notifyRemoteStartTransactionRejected(
chargingStation,
transactionConnectorId,
- idTag,
- );
+ idTag
+ )
}
if (
!chargingStation.isChargingStationAvailable() ||
!chargingStation.isConnectorAvailable(transactionConnectorId)
) {
- return this.notifyRemoteStartTransactionRejected(
+ return await this.notifyRemoteStartTransactionRejected(
chargingStation,
transactionConnectorId,
- idTag,
- );
+ idTag
+ )
}
const remoteStartTransactionLogMsg = `
${chargingStation.logPrefix()} Transaction remotely STARTED on ${
chargingStation.stationInfo.chargingStationId
- }#${transactionConnectorId} for idTag '${idTag}'`;
+ }#${transactionConnectorId} for idTag '${idTag}'`
await OCPP16ServiceUtils.sendAndSetConnectorStatus(
chargingStation,
transactionConnectorId,
- OCPP16ChargePointStatus.Preparing,
- );
- const connectorStatus = chargingStation.getConnectorStatus(transactionConnectorId)!;
+ OCPP16ChargePointStatus.Preparing
+ )
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ const connectorStatus = chargingStation.getConnectorStatus(transactionConnectorId)!
// Authorization check required
if (
- chargingStation.getAuthorizeRemoteTxRequests() === true &&
+ chargingStation.getAuthorizeRemoteTxRequests() &&
(await OCPP16ServiceUtils.isIdTagAuthorized(chargingStation, transactionConnectorId, idTag))
) {
// Authorization successful, start transaction
if (
- (chargingProfile &&
+ (chargingProfile != null &&
this.setRemoteStartTransactionChargingProfile(
chargingStation,
transactionConnectorId,
- chargingProfile,
- // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
- ) === true) ||
- !chargingProfile
+ chargingProfile
+ )) ||
+ chargingProfile == null
) {
- connectorStatus.transactionRemoteStarted = true;
+ connectorStatus.transactionRemoteStarted = true
if (
(
await chargingStation.ocppRequestService.requestHandler<
- OCPP16StartTransactionRequest,
- OCPP16StartTransactionResponse
+ OCPP16StartTransactionRequest,
+ OCPP16StartTransactionResponse
>(chargingStation, OCPP16RequestCommand.START_TRANSACTION, {
connectorId: transactionConnectorId,
- idTag,
+ idTag
})
).idTagInfo.status === OCPP16AuthorizationStatus.ACCEPTED
) {
- logger.debug(remoteStartTransactionLogMsg);
- return OCPP16Constants.OCPP_RESPONSE_ACCEPTED;
+ logger.debug(remoteStartTransactionLogMsg)
+ return OCPP16Constants.OCPP_RESPONSE_ACCEPTED
}
- return this.notifyRemoteStartTransactionRejected(
+ return await this.notifyRemoteStartTransactionRejected(
chargingStation,
transactionConnectorId,
- idTag,
- );
+ idTag
+ )
}
- return this.notifyRemoteStartTransactionRejected(
+ return await this.notifyRemoteStartTransactionRejected(
chargingStation,
transactionConnectorId,
- idTag,
- );
+ idTag
+ )
}
// No authorization check required, start transaction
if (
- (chargingProfile &&
+ (chargingProfile != null &&
this.setRemoteStartTransactionChargingProfile(
chargingStation,
transactionConnectorId,
- chargingProfile,
- // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
- ) === true) ||
- !chargingProfile
+ chargingProfile
+ )) ||
+ chargingProfile == null
) {
- connectorStatus.transactionRemoteStarted = true;
+ connectorStatus.transactionRemoteStarted = true
if (
(
await chargingStation.ocppRequestService.requestHandler<
- OCPP16StartTransactionRequest,
- OCPP16StartTransactionResponse
+ OCPP16StartTransactionRequest,
+ OCPP16StartTransactionResponse
>(chargingStation, OCPP16RequestCommand.START_TRANSACTION, {
connectorId: transactionConnectorId,
- idTag,
+ idTag
})
).idTagInfo.status === OCPP16AuthorizationStatus.ACCEPTED
) {
- logger.debug(remoteStartTransactionLogMsg);
- return OCPP16Constants.OCPP_RESPONSE_ACCEPTED;
+ logger.debug(remoteStartTransactionLogMsg)
+ return OCPP16Constants.OCPP_RESPONSE_ACCEPTED
}
- return this.notifyRemoteStartTransactionRejected(
+ return await this.notifyRemoteStartTransactionRejected(
chargingStation,
transactionConnectorId,
- idTag,
- );
+ idTag
+ )
}
- return this.notifyRemoteStartTransactionRejected(
+ return await this.notifyRemoteStartTransactionRejected(
chargingStation,
transactionConnectorId,
- idTag,
- );
+ idTag
+ )
}
- private async notifyRemoteStartTransactionRejected(
+ private async notifyRemoteStartTransactionRejected (
chargingStation: ChargingStation,
connectorId: number,
- idTag: string,
+ idTag: string
): Promise<GenericResponse> {
- const connectorStatus = chargingStation.getConnectorStatus(connectorId);
+ const connectorStatus = chargingStation.getConnectorStatus(connectorId)
if (connectorStatus?.status !== OCPP16ChargePointStatus.Available) {
await OCPP16ServiceUtils.sendAndSetConnectorStatus(
chargingStation,
connectorId,
- OCPP16ChargePointStatus.Available,
- );
+ OCPP16ChargePointStatus.Available
+ )
}
logger.warn(
- `${chargingStation.logPrefix()} Remote starting transaction REJECTED on connector id ${connectorId}, idTag '${idTag}', availability '${connectorStatus?.availability}', status '${connectorStatus?.status}'`,
- );
- return OCPP16Constants.OCPP_RESPONSE_REJECTED;
+ `${chargingStation.logPrefix()} Remote starting transaction REJECTED on connector id ${connectorId}, idTag '${idTag}', availability '${connectorStatus?.availability}', status '${connectorStatus?.status}'`
+ )
+ return OCPP16Constants.OCPP_RESPONSE_REJECTED
}
- private setRemoteStartTransactionChargingProfile(
+ private setRemoteStartTransactionChargingProfile (
chargingStation: ChargingStation,
connectorId: number,
- chargingProfile: OCPP16ChargingProfile,
+ chargingProfile: OCPP16ChargingProfile
): boolean {
if (chargingProfile?.chargingProfilePurpose === OCPP16ChargingProfilePurposeType.TX_PROFILE) {
- OCPP16ServiceUtils.setChargingProfile(chargingStation, connectorId, chargingProfile);
+ OCPP16ServiceUtils.setChargingProfile(chargingStation, connectorId, chargingProfile)
logger.debug(
`${chargingStation.logPrefix()} Charging profile(s) set at remote start transaction on connector id ${connectorId}: %j`,
- chargingProfile,
- );
- return true;
+ chargingProfile
+ )
+ return true
}
logger.warn(
`${chargingStation.logPrefix()} Not allowed to set ${
chargingProfile.chargingProfilePurpose
- } charging profile(s) at remote start transaction`,
- );
- return false;
+ } charging profile(s) at remote start transaction`
+ )
+ return false
}
- private async handleRequestRemoteStopTransaction(
+ private async handleRequestRemoteStopTransaction (
chargingStation: ChargingStation,
- commandPayload: RemoteStopTransactionRequest,
+ commandPayload: RemoteStopTransactionRequest
): Promise<GenericResponse> {
- const { transactionId } = commandPayload;
+ const { transactionId } = commandPayload
if (chargingStation.hasEvses) {
for (const [evseId, evseStatus] of chargingStation.evses) {
if (evseId > 0) {
for (const [connectorId, connectorStatus] of evseStatus.connectors) {
if (connectorStatus.transactionId === transactionId) {
- return OCPP16ServiceUtils.remoteStopTransaction(chargingStation, connectorId);
+ return await OCPP16ServiceUtils.remoteStopTransaction(chargingStation, connectorId)
}
}
}
connectorId > 0 &&
chargingStation.getConnectorStatus(connectorId)?.transactionId === transactionId
) {
- return OCPP16ServiceUtils.remoteStopTransaction(chargingStation, connectorId);
+ return await OCPP16ServiceUtils.remoteStopTransaction(chargingStation, connectorId)
}
}
}
logger.warn(
- `${chargingStation.logPrefix()} Trying to remote stop a non existing transaction with id ${transactionId}`,
- );
- return OCPP16Constants.OCPP_RESPONSE_REJECTED;
+ `${chargingStation.logPrefix()} Trying to remote stop a non existing transaction with id ${transactionId}`
+ )
+ return OCPP16Constants.OCPP_RESPONSE_REJECTED
}
- private handleRequestUpdateFirmware(
+ private handleRequestUpdateFirmware (
chargingStation: ChargingStation,
- commandPayload: OCPP16UpdateFirmwareRequest,
+ commandPayload: OCPP16UpdateFirmwareRequest
): OCPP16UpdateFirmwareResponse {
if (
- OCPP16ServiceUtils.checkFeatureProfile(
+ !OCPP16ServiceUtils.checkFeatureProfile(
chargingStation,
OCPP16SupportedFeatureProfiles.FirmwareManagement,
- OCPP16IncomingRequestCommand.UPDATE_FIRMWARE,
- ) === false
+ OCPP16IncomingRequestCommand.UPDATE_FIRMWARE
+ )
) {
logger.warn(
- `${chargingStation.logPrefix()} ${moduleName}.handleRequestUpdateFirmware: Cannot simulate firmware update: feature profile not supported`,
- );
- return OCPP16Constants.OCPP_RESPONSE_EMPTY;
+ `${chargingStation.logPrefix()} ${moduleName}.handleRequestUpdateFirmware: Cannot simulate firmware update: feature profile not supported`
+ )
+ return OCPP16Constants.OCPP_RESPONSE_EMPTY
}
- let { retrieveDate } = commandPayload;
+ let { retrieveDate } = commandPayload
if (
!isNullOrUndefined(chargingStation.stationInfo.firmwareStatus) &&
chargingStation.stationInfo.firmwareStatus !== OCPP16FirmwareStatus.Installed
) {
logger.warn(
- `${chargingStation.logPrefix()} ${moduleName}.handleRequestUpdateFirmware: Cannot simulate firmware update: firmware update is already in progress`,
- );
- return OCPP16Constants.OCPP_RESPONSE_EMPTY;
+ `${chargingStation.logPrefix()} ${moduleName}.handleRequestUpdateFirmware: Cannot simulate firmware update: firmware update is already in progress`
+ )
+ return OCPP16Constants.OCPP_RESPONSE_EMPTY
}
- retrieveDate = convertToDate(retrieveDate)!;
- const now = Date.now();
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ retrieveDate = convertToDate(retrieveDate)!
+ const now = Date.now()
if (retrieveDate?.getTime() <= now) {
- this.updateFirmwareSimulation(chargingStation).catch(Constants.EMPTY_FUNCTION);
+ this.updateFirmwareSimulation(chargingStation).catch(Constants.EMPTY_FUNCTION)
} else {
setTimeout(
() => {
- this.updateFirmwareSimulation(chargingStation).catch(Constants.EMPTY_FUNCTION);
+ this.updateFirmwareSimulation(chargingStation).catch(Constants.EMPTY_FUNCTION)
},
- retrieveDate?.getTime() - now,
- );
+ retrieveDate?.getTime() - now
+ )
}
- return OCPP16Constants.OCPP_RESPONSE_EMPTY;
+ return OCPP16Constants.OCPP_RESPONSE_EMPTY
}
- private async updateFirmwareSimulation(
+ private async updateFirmwareSimulation (
chargingStation: ChargingStation,
maxDelay = 30,
- minDelay = 15,
+ minDelay = 15
): Promise<void> {
- if (checkChargingStation(chargingStation, chargingStation.logPrefix()) === false) {
- return;
+ if (!checkChargingStation(chargingStation, chargingStation.logPrefix())) {
+ return
}
if (chargingStation.hasEvses) {
for (const [evseId, evseStatus] of chargingStation.evses) {
await OCPP16ServiceUtils.sendAndSetConnectorStatus(
chargingStation,
connectorId,
- OCPP16ChargePointStatus.Unavailable,
- );
+ OCPP16ChargePointStatus.Unavailable
+ )
}
}
}
await OCPP16ServiceUtils.sendAndSetConnectorStatus(
chargingStation,
connectorId,
- OCPP16ChargePointStatus.Unavailable,
- );
+ OCPP16ChargePointStatus.Unavailable
+ )
}
}
}
await chargingStation.ocppRequestService.requestHandler<
- OCPP16FirmwareStatusNotificationRequest,
- OCPP16FirmwareStatusNotificationResponse
+ OCPP16FirmwareStatusNotificationRequest,
+ OCPP16FirmwareStatusNotificationResponse
>(chargingStation, OCPP16RequestCommand.FIRMWARE_STATUS_NOTIFICATION, {
- status: OCPP16FirmwareStatus.Downloading,
- });
- chargingStation.stationInfo.firmwareStatus = OCPP16FirmwareStatus.Downloading;
+ status: OCPP16FirmwareStatus.Downloading
+ })
+ chargingStation.stationInfo.firmwareStatus = OCPP16FirmwareStatus.Downloading
if (
chargingStation.stationInfo?.firmwareUpgrade?.failureStatus ===
OCPP16FirmwareStatus.DownloadFailed
) {
- await sleep(secondsToMilliseconds(getRandomInteger(maxDelay, minDelay)));
+ await sleep(secondsToMilliseconds(getRandomInteger(maxDelay, minDelay)))
await chargingStation.ocppRequestService.requestHandler<
- OCPP16FirmwareStatusNotificationRequest,
- OCPP16FirmwareStatusNotificationResponse
+ OCPP16FirmwareStatusNotificationRequest,
+ OCPP16FirmwareStatusNotificationResponse
>(chargingStation, OCPP16RequestCommand.FIRMWARE_STATUS_NOTIFICATION, {
- status: chargingStation.stationInfo?.firmwareUpgrade?.failureStatus,
- });
+ status: chargingStation.stationInfo?.firmwareUpgrade?.failureStatus
+ })
chargingStation.stationInfo.firmwareStatus =
- chargingStation.stationInfo?.firmwareUpgrade?.failureStatus;
- return;
+ chargingStation.stationInfo?.firmwareUpgrade?.failureStatus
+ return
}
- await sleep(secondsToMilliseconds(getRandomInteger(maxDelay, minDelay)));
+ await sleep(secondsToMilliseconds(getRandomInteger(maxDelay, minDelay)))
await chargingStation.ocppRequestService.requestHandler<
- OCPP16FirmwareStatusNotificationRequest,
- OCPP16FirmwareStatusNotificationResponse
+ OCPP16FirmwareStatusNotificationRequest,
+ OCPP16FirmwareStatusNotificationResponse
>(chargingStation, OCPP16RequestCommand.FIRMWARE_STATUS_NOTIFICATION, {
- status: OCPP16FirmwareStatus.Downloaded,
- });
- chargingStation.stationInfo.firmwareStatus = OCPP16FirmwareStatus.Downloaded;
- let wasTransactionsStarted = false;
- let transactionsStarted: boolean;
+ status: OCPP16FirmwareStatus.Downloaded
+ })
+ chargingStation.stationInfo.firmwareStatus = OCPP16FirmwareStatus.Downloaded
+ let wasTransactionsStarted = false
+ let transactionsStarted: boolean
do {
- const runningTransactions = chargingStation.getNumberOfRunningTransactions();
+ const runningTransactions = chargingStation.getNumberOfRunningTransactions()
if (runningTransactions > 0) {
- const waitTime = secondsToMilliseconds(15);
+ const waitTime = secondsToMilliseconds(15)
logger.debug(
`${chargingStation.logPrefix()} ${moduleName}.updateFirmwareSimulation: ${runningTransactions} transaction(s) in progress, waiting ${formatDurationMilliSeconds(
- waitTime,
- )} before continuing firmware update simulation`,
- );
- await sleep(waitTime);
- transactionsStarted = true;
- wasTransactionsStarted = true;
+ waitTime
+ )} before continuing firmware update simulation`
+ )
+ await sleep(waitTime)
+ transactionsStarted = true
+ wasTransactionsStarted = true
} else {
if (chargingStation.hasEvses) {
for (const [evseId, evseStatus] of chargingStation.evses) {
await OCPP16ServiceUtils.sendAndSetConnectorStatus(
chargingStation,
connectorId,
- OCPP16ChargePointStatus.Unavailable,
- );
+ OCPP16ChargePointStatus.Unavailable
+ )
}
}
}
await OCPP16ServiceUtils.sendAndSetConnectorStatus(
chargingStation,
connectorId,
- OCPP16ChargePointStatus.Unavailable,
- );
+ OCPP16ChargePointStatus.Unavailable
+ )
}
}
}
- transactionsStarted = false;
+ transactionsStarted = false
}
- } while (transactionsStarted);
+ } while (transactionsStarted)
!wasTransactionsStarted &&
- (await sleep(secondsToMilliseconds(getRandomInteger(maxDelay, minDelay))));
- if (checkChargingStation(chargingStation, chargingStation.logPrefix()) === false) {
- return;
+ (await sleep(secondsToMilliseconds(getRandomInteger(maxDelay, minDelay))))
+ if (!checkChargingStation(chargingStation, chargingStation.logPrefix())) {
+ return
}
await chargingStation.ocppRequestService.requestHandler<
- OCPP16FirmwareStatusNotificationRequest,
- OCPP16FirmwareStatusNotificationResponse
+ OCPP16FirmwareStatusNotificationRequest,
+ OCPP16FirmwareStatusNotificationResponse
>(chargingStation, OCPP16RequestCommand.FIRMWARE_STATUS_NOTIFICATION, {
- status: OCPP16FirmwareStatus.Installing,
- });
- chargingStation.stationInfo.firmwareStatus = OCPP16FirmwareStatus.Installing;
+ status: OCPP16FirmwareStatus.Installing
+ })
+ chargingStation.stationInfo.firmwareStatus = OCPP16FirmwareStatus.Installing
if (
chargingStation.stationInfo?.firmwareUpgrade?.failureStatus ===
OCPP16FirmwareStatus.InstallationFailed
) {
- await sleep(secondsToMilliseconds(getRandomInteger(maxDelay, minDelay)));
+ await sleep(secondsToMilliseconds(getRandomInteger(maxDelay, minDelay)))
await chargingStation.ocppRequestService.requestHandler<
- OCPP16FirmwareStatusNotificationRequest,
- OCPP16FirmwareStatusNotificationResponse
+ OCPP16FirmwareStatusNotificationRequest,
+ OCPP16FirmwareStatusNotificationResponse
>(chargingStation, OCPP16RequestCommand.FIRMWARE_STATUS_NOTIFICATION, {
- status: chargingStation.stationInfo?.firmwareUpgrade?.failureStatus,
- });
+ status: chargingStation.stationInfo?.firmwareUpgrade?.failureStatus
+ })
chargingStation.stationInfo.firmwareStatus =
- chargingStation.stationInfo?.firmwareUpgrade?.failureStatus;
- return;
+ chargingStation.stationInfo?.firmwareUpgrade?.failureStatus
+ return
}
if (chargingStation.stationInfo?.firmwareUpgrade?.reset === true) {
- await sleep(secondsToMilliseconds(getRandomInteger(maxDelay, minDelay)));
- await chargingStation.reset(OCPP16StopTransactionReason.REBOOT);
+ await sleep(secondsToMilliseconds(getRandomInteger(maxDelay, minDelay)))
+ await chargingStation.reset(OCPP16StopTransactionReason.REBOOT)
}
}
- private async handleRequestGetDiagnostics(
+ private async handleRequestGetDiagnostics (
chargingStation: ChargingStation,
- commandPayload: GetDiagnosticsRequest,
+ commandPayload: GetDiagnosticsRequest
): Promise<GetDiagnosticsResponse> {
if (
- OCPP16ServiceUtils.checkFeatureProfile(
+ !OCPP16ServiceUtils.checkFeatureProfile(
chargingStation,
OCPP16SupportedFeatureProfiles.FirmwareManagement,
- OCPP16IncomingRequestCommand.GET_DIAGNOSTICS,
- ) === false
+ OCPP16IncomingRequestCommand.GET_DIAGNOSTICS
+ )
) {
logger.warn(
- `${chargingStation.logPrefix()} ${moduleName}.handleRequestGetDiagnostics: Cannot get diagnostics: feature profile not supported`,
- );
- return OCPP16Constants.OCPP_RESPONSE_EMPTY;
+ `${chargingStation.logPrefix()} ${moduleName}.handleRequestGetDiagnostics: Cannot get diagnostics: feature profile not supported`
+ )
+ return OCPP16Constants.OCPP_RESPONSE_EMPTY
}
- const { location } = commandPayload;
- const uri = new URL(location);
+ const { location } = commandPayload
+ const uri = new URL(location)
if (uri.protocol.startsWith('ftp:')) {
- let ftpClient: Client | undefined;
+ let ftpClient: Client | undefined
try {
const logFiles = readdirSync(resolve(dirname(fileURLToPath(import.meta.url)), '../'))
.filter((file) => file.endsWith('.log'))
- .map((file) => join('./', file));
- const diagnosticsArchive = `${chargingStation.stationInfo.chargingStationId}_logs.tar.gz`;
- create({ gzip: true }, logFiles).pipe(createWriteStream(diagnosticsArchive));
- ftpClient = new Client();
+ .map((file) => join('./', file))
+ const diagnosticsArchive = `${chargingStation.stationInfo.chargingStationId}_logs.tar.gz`
+ create({ gzip: true }, logFiles).pipe(createWriteStream(diagnosticsArchive))
+ ftpClient = new Client()
const accessResponse = await ftpClient.access({
host: uri.host,
...(isNotEmptyString(uri.port) && { port: convertToInt(uri.port) }),
...(isNotEmptyString(uri.username) && { user: uri.username }),
- ...(isNotEmptyString(uri.password) && { password: uri.password }),
- });
- let uploadResponse: FTPResponse | undefined;
+ ...(isNotEmptyString(uri.password) && { password: uri.password })
+ })
+ let uploadResponse: FTPResponse | undefined
if (accessResponse.code === 220) {
ftpClient.trackProgress((info) => {
logger.info(
`${chargingStation.logPrefix()} ${moduleName}.handleRequestGetDiagnostics: ${
info.bytes / 1024
- } bytes transferred from diagnostics archive ${info.name}`,
- );
+ } bytes transferred from diagnostics archive ${info.name}`
+ )
chargingStation.ocppRequestService
.requestHandler<
- OCPP16DiagnosticsStatusNotificationRequest,
- OCPP16DiagnosticsStatusNotificationResponse
- >(chargingStation, OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION, {
- status: OCPP16DiagnosticsStatus.Uploading,
- })
+ OCPP16DiagnosticsStatusNotificationRequest,
+ OCPP16DiagnosticsStatusNotificationResponse
+ >(chargingStation, OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION, {
+ status: OCPP16DiagnosticsStatus.Uploading
+ })
.catch((error) => {
logger.error(
`${chargingStation.logPrefix()} ${moduleName}.handleRequestGetDiagnostics: Error while sending '${
OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION
}'`,
- error,
- );
- });
- });
+ error
+ )
+ })
+ })
uploadResponse = await ftpClient.uploadFrom(
join(resolve(dirname(fileURLToPath(import.meta.url)), '../'), diagnosticsArchive),
- `${uri.pathname}${diagnosticsArchive}`,
- );
+ `${uri.pathname}${diagnosticsArchive}`
+ )
if (uploadResponse.code === 226) {
await chargingStation.ocppRequestService.requestHandler<
- OCPP16DiagnosticsStatusNotificationRequest,
- OCPP16DiagnosticsStatusNotificationResponse
+ OCPP16DiagnosticsStatusNotificationRequest,
+ OCPP16DiagnosticsStatusNotificationResponse
>(chargingStation, OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION, {
- status: OCPP16DiagnosticsStatus.Uploaded,
- });
- if (ftpClient) {
- ftpClient.close();
+ status: OCPP16DiagnosticsStatus.Uploaded
+ })
+ if (ftpClient != null) {
+ ftpClient.close()
}
- return { fileName: diagnosticsArchive };
+ return { fileName: diagnosticsArchive }
}
throw new OCPPError(
ErrorType.GENERIC_ERROR,
`Diagnostics transfer failed with error code ${accessResponse.code}${
- uploadResponse?.code && `|${uploadResponse?.code}`
+ uploadResponse?.code != null && `|${uploadResponse?.code}`
}`,
- OCPP16IncomingRequestCommand.GET_DIAGNOSTICS,
- );
+ OCPP16IncomingRequestCommand.GET_DIAGNOSTICS
+ )
}
throw new OCPPError(
ErrorType.GENERIC_ERROR,
`Diagnostics transfer failed with error code ${accessResponse.code}${
- uploadResponse?.code && `|${uploadResponse?.code}`
+ uploadResponse?.code != null && `|${uploadResponse?.code}`
}`,
- OCPP16IncomingRequestCommand.GET_DIAGNOSTICS,
- );
+ OCPP16IncomingRequestCommand.GET_DIAGNOSTICS
+ )
} catch (error) {
await chargingStation.ocppRequestService.requestHandler<
- OCPP16DiagnosticsStatusNotificationRequest,
- OCPP16DiagnosticsStatusNotificationResponse
+ OCPP16DiagnosticsStatusNotificationRequest,
+ OCPP16DiagnosticsStatusNotificationResponse
>(chargingStation, OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION, {
- status: OCPP16DiagnosticsStatus.UploadFailed,
- });
- if (ftpClient) {
- ftpClient.close();
+ status: OCPP16DiagnosticsStatus.UploadFailed
+ })
+ if (ftpClient != null) {
+ ftpClient.close()
}
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
return this.handleIncomingRequestError<GetDiagnosticsResponse>(
chargingStation,
OCPP16IncomingRequestCommand.GET_DIAGNOSTICS,
error as Error,
- { errorResponse: OCPP16Constants.OCPP_RESPONSE_EMPTY },
- )!;
+ { errorResponse: OCPP16Constants.OCPP_RESPONSE_EMPTY }
+ )!
}
} else {
logger.error(
`${chargingStation.logPrefix()} Unsupported protocol ${
uri.protocol
- } to transfer the diagnostic logs archive`,
- );
+ } to transfer the diagnostic logs archive`
+ )
await chargingStation.ocppRequestService.requestHandler<
- OCPP16DiagnosticsStatusNotificationRequest,
- OCPP16DiagnosticsStatusNotificationResponse
+ OCPP16DiagnosticsStatusNotificationRequest,
+ OCPP16DiagnosticsStatusNotificationResponse
>(chargingStation, OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION, {
- status: OCPP16DiagnosticsStatus.UploadFailed,
- });
- return OCPP16Constants.OCPP_RESPONSE_EMPTY;
+ status: OCPP16DiagnosticsStatus.UploadFailed
+ })
+ return OCPP16Constants.OCPP_RESPONSE_EMPTY
}
}
- private handleRequestTriggerMessage(
+ private handleRequestTriggerMessage (
chargingStation: ChargingStation,
- commandPayload: OCPP16TriggerMessageRequest,
+ commandPayload: OCPP16TriggerMessageRequest
): OCPP16TriggerMessageResponse {
- const { requestedMessage, connectorId } = commandPayload;
+ const { requestedMessage, connectorId } = commandPayload
if (
!OCPP16ServiceUtils.checkFeatureProfile(
chargingStation,
OCPP16SupportedFeatureProfiles.RemoteTrigger,
- OCPP16IncomingRequestCommand.TRIGGER_MESSAGE,
+ OCPP16IncomingRequestCommand.TRIGGER_MESSAGE
) ||
!OCPP16ServiceUtils.isMessageTriggerSupported(chargingStation, requestedMessage)
) {
- return OCPP16Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_NOT_IMPLEMENTED;
+ return OCPP16Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_NOT_IMPLEMENTED
}
if (
!OCPP16ServiceUtils.isConnectorIdValid(
chargingStation,
OCPP16IncomingRequestCommand.TRIGGER_MESSAGE,
- connectorId!,
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ connectorId!
)
) {
- return OCPP16Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_REJECTED;
+ return OCPP16Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_REJECTED
}
try {
switch (requestedMessage) {
setTimeout(() => {
chargingStation.ocppRequestService
.requestHandler<OCPP16BootNotificationRequest, OCPP16BootNotificationResponse>(
- chargingStation,
- OCPP16RequestCommand.BOOT_NOTIFICATION,
- chargingStation.bootNotificationRequest,
- { skipBufferingOnError: true, triggerMessage: true },
- )
+ chargingStation,
+ OCPP16RequestCommand.BOOT_NOTIFICATION,
+ chargingStation.bootNotificationRequest,
+ { skipBufferingOnError: true, triggerMessage: true }
+ )
.then((response) => {
- chargingStation.bootNotificationResponse = response;
+ chargingStation.bootNotificationResponse = response
})
- .catch(Constants.EMPTY_FUNCTION);
- }, OCPP16Constants.OCPP_TRIGGER_MESSAGE_DELAY);
- return OCPP16Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_ACCEPTED;
+ .catch(Constants.EMPTY_FUNCTION)
+ }, OCPP16Constants.OCPP_TRIGGER_MESSAGE_DELAY)
+ return OCPP16Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_ACCEPTED
case OCPP16MessageTrigger.Heartbeat:
setTimeout(() => {
chargingStation.ocppRequestService
.requestHandler<OCPP16HeartbeatRequest, OCPP16HeartbeatResponse>(
- chargingStation,
- OCPP16RequestCommand.HEARTBEAT,
- undefined,
- {
- triggerMessage: true,
- },
- )
- .catch(Constants.EMPTY_FUNCTION);
- }, OCPP16Constants.OCPP_TRIGGER_MESSAGE_DELAY);
- return OCPP16Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_ACCEPTED;
+ chargingStation,
+ OCPP16RequestCommand.HEARTBEAT,
+ undefined,
+ {
+ triggerMessage: true
+ }
+ )
+ .catch(Constants.EMPTY_FUNCTION)
+ }, OCPP16Constants.OCPP_TRIGGER_MESSAGE_DELAY)
+ return OCPP16Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_ACCEPTED
case OCPP16MessageTrigger.StatusNotification:
setTimeout(() => {
if (!isNullOrUndefined(connectorId)) {
chargingStation.ocppRequestService
.requestHandler<OCPP16StatusNotificationRequest, OCPP16StatusNotificationResponse>(
- chargingStation,
- OCPP16RequestCommand.STATUS_NOTIFICATION,
- {
- connectorId,
- errorCode: OCPP16ChargePointErrorCode.NO_ERROR,
- status: chargingStation.getConnectorStatus(connectorId!)?.status,
- },
- {
- triggerMessage: true,
- },
- )
- .catch(Constants.EMPTY_FUNCTION);
+ chargingStation,
+ OCPP16RequestCommand.STATUS_NOTIFICATION,
+ {
+ connectorId,
+ errorCode: OCPP16ChargePointErrorCode.NO_ERROR,
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ status: chargingStation.getConnectorStatus(connectorId!)?.status
+ },
+ {
+ triggerMessage: true
+ }
+ )
+ .catch(Constants.EMPTY_FUNCTION)
} else {
- // eslint-disable-next-line no-lonely-if
if (chargingStation.hasEvses) {
for (const evseStatus of chargingStation.evses.values()) {
for (const [id, connectorStatus] of evseStatus.connectors) {
chargingStation.ocppRequestService
.requestHandler<
- OCPP16StatusNotificationRequest,
- OCPP16StatusNotificationResponse
- >(
- chargingStation,
- OCPP16RequestCommand.STATUS_NOTIFICATION,
- {
- connectorId: id,
- errorCode: OCPP16ChargePointErrorCode.NO_ERROR,
- status: connectorStatus.status,
- },
- {
- triggerMessage: true,
- },
- )
- .catch(Constants.EMPTY_FUNCTION);
- }
- }
- } else {
- for (const id of chargingStation.connectors.keys()) {
- chargingStation.ocppRequestService
- .requestHandler<
- OCPP16StatusNotificationRequest,
- OCPP16StatusNotificationResponse
+ OCPP16StatusNotificationRequest,
+ OCPP16StatusNotificationResponse
>(
chargingStation,
OCPP16RequestCommand.STATUS_NOTIFICATION,
{
connectorId: id,
errorCode: OCPP16ChargePointErrorCode.NO_ERROR,
- status: chargingStation.getConnectorStatus(id)?.status,
+ status: connectorStatus.status
},
{
- triggerMessage: true,
- },
+ triggerMessage: true
+ }
)
- .catch(Constants.EMPTY_FUNCTION);
+ .catch(Constants.EMPTY_FUNCTION)
+ }
+ }
+ } else {
+ for (const id of chargingStation.connectors.keys()) {
+ chargingStation.ocppRequestService
+ .requestHandler<
+ OCPP16StatusNotificationRequest,
+ OCPP16StatusNotificationResponse
+ >(
+ chargingStation,
+ OCPP16RequestCommand.STATUS_NOTIFICATION,
+ {
+ connectorId: id,
+ errorCode: OCPP16ChargePointErrorCode.NO_ERROR,
+ status: chargingStation.getConnectorStatus(id)?.status
+ },
+ {
+ triggerMessage: true
+ }
+ )
+ .catch(Constants.EMPTY_FUNCTION)
}
}
}
- }, OCPP16Constants.OCPP_TRIGGER_MESSAGE_DELAY);
- return OCPP16Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_ACCEPTED;
+ }, OCPP16Constants.OCPP_TRIGGER_MESSAGE_DELAY)
+ return OCPP16Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_ACCEPTED
default:
- return OCPP16Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_NOT_IMPLEMENTED;
+ return OCPP16Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_NOT_IMPLEMENTED
}
} catch (error) {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
return this.handleIncomingRequestError<OCPP16TriggerMessageResponse>(
chargingStation,
OCPP16IncomingRequestCommand.TRIGGER_MESSAGE,
error as Error,
- { errorResponse: OCPP16Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_REJECTED },
- )!;
+ { errorResponse: OCPP16Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_REJECTED }
+ )!
}
}
- private handleRequestDataTransfer(
+ private handleRequestDataTransfer (
chargingStation: ChargingStation,
- commandPayload: OCPP16DataTransferRequest,
+ commandPayload: OCPP16DataTransferRequest
): OCPP16DataTransferResponse {
- const { vendorId } = commandPayload;
+ const { vendorId } = commandPayload
try {
if (Object.values(OCPP16DataTransferVendorId).includes(vendorId)) {
- return OCPP16Constants.OCPP_DATA_TRANSFER_RESPONSE_ACCEPTED;
+ return OCPP16Constants.OCPP_DATA_TRANSFER_RESPONSE_ACCEPTED
}
- return OCPP16Constants.OCPP_DATA_TRANSFER_RESPONSE_UNKNOWN_VENDOR_ID;
+ return OCPP16Constants.OCPP_DATA_TRANSFER_RESPONSE_UNKNOWN_VENDOR_ID
} catch (error) {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
return this.handleIncomingRequestError<OCPP16DataTransferResponse>(
chargingStation,
OCPP16IncomingRequestCommand.DATA_TRANSFER,
error as Error,
- { errorResponse: OCPP16Constants.OCPP_DATA_TRANSFER_RESPONSE_REJECTED },
- )!;
+ { errorResponse: OCPP16Constants.OCPP_DATA_TRANSFER_RESPONSE_REJECTED }
+ )!
}
}
- private async handleRequestReserveNow(
+ private async handleRequestReserveNow (
chargingStation: ChargingStation,
- commandPayload: OCPP16ReserveNowRequest,
+ commandPayload: OCPP16ReserveNowRequest
): Promise<OCPP16ReserveNowResponse> {
if (
!OCPP16ServiceUtils.checkFeatureProfile(
chargingStation,
OCPP16SupportedFeatureProfiles.Reservation,
- OCPP16IncomingRequestCommand.RESERVE_NOW,
+ OCPP16IncomingRequestCommand.RESERVE_NOW
)
) {
- return OCPP16Constants.OCPP_RESERVATION_RESPONSE_REJECTED;
+ return OCPP16Constants.OCPP_RESERVATION_RESPONSE_REJECTED
}
- const { reservationId, idTag, connectorId } = commandPayload;
- let response: OCPP16ReserveNowResponse;
+ const { reservationId, idTag, connectorId } = commandPayload
+ let response: OCPP16ReserveNowResponse
try {
if (connectorId > 0 && !chargingStation.isConnectorAvailable(connectorId)) {
- return OCPP16Constants.OCPP_RESERVATION_RESPONSE_REJECTED;
+ return OCPP16Constants.OCPP_RESERVATION_RESPONSE_REJECTED
}
if (connectorId === 0 && !chargingStation.getReserveConnectorZeroSupported()) {
- return OCPP16Constants.OCPP_RESERVATION_RESPONSE_REJECTED;
+ return OCPP16Constants.OCPP_RESERVATION_RESPONSE_REJECTED
}
if (!(await OCPP16ServiceUtils.isIdTagAuthorized(chargingStation, connectorId, idTag))) {
- return OCPP16Constants.OCPP_RESERVATION_RESPONSE_REJECTED;
+ return OCPP16Constants.OCPP_RESERVATION_RESPONSE_REJECTED
}
- await removeExpiredReservations(chargingStation);
+ await removeExpiredReservations(chargingStation)
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
switch (chargingStation.getConnectorStatus(connectorId)!.status) {
case OCPP16ChargePointStatus.Faulted:
- response = OCPP16Constants.OCPP_RESERVATION_RESPONSE_FAULTED;
- break;
+ response = OCPP16Constants.OCPP_RESERVATION_RESPONSE_FAULTED
+ break
case OCPP16ChargePointStatus.Preparing:
case OCPP16ChargePointStatus.Charging:
case OCPP16ChargePointStatus.SuspendedEV:
case OCPP16ChargePointStatus.SuspendedEVSE:
case OCPP16ChargePointStatus.Finishing:
- response = OCPP16Constants.OCPP_RESERVATION_RESPONSE_OCCUPIED;
- break;
+ response = OCPP16Constants.OCPP_RESERVATION_RESPONSE_OCCUPIED
+ break
case OCPP16ChargePointStatus.Unavailable:
- response = OCPP16Constants.OCPP_RESERVATION_RESPONSE_UNAVAILABLE;
- break;
+ response = OCPP16Constants.OCPP_RESERVATION_RESPONSE_UNAVAILABLE
+ break
case OCPP16ChargePointStatus.Reserved:
if (!chargingStation.isConnectorReservable(reservationId, idTag, connectorId)) {
- response = OCPP16Constants.OCPP_RESERVATION_RESPONSE_OCCUPIED;
- break;
+ response = OCPP16Constants.OCPP_RESERVATION_RESPONSE_OCCUPIED
+ break
}
// eslint-disable-next-line no-fallthrough
default:
if (!chargingStation.isConnectorReservable(reservationId, idTag)) {
- response = OCPP16Constants.OCPP_RESERVATION_RESPONSE_OCCUPIED;
- break;
+ response = OCPP16Constants.OCPP_RESERVATION_RESPONSE_OCCUPIED
+ break
}
await chargingStation.addReservation({
id: commandPayload.reservationId,
- ...commandPayload,
- });
- response = OCPP16Constants.OCPP_RESERVATION_RESPONSE_ACCEPTED;
- break;
+ ...commandPayload
+ })
+ response = OCPP16Constants.OCPP_RESERVATION_RESPONSE_ACCEPTED
+ break
}
- return response;
+ return response
} catch (error) {
- chargingStation.getConnectorStatus(connectorId)!.status = OCPP16ChargePointStatus.Available;
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ chargingStation.getConnectorStatus(connectorId)!.status = OCPP16ChargePointStatus.Available
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
return this.handleIncomingRequestError<OCPP16ReserveNowResponse>(
chargingStation,
OCPP16IncomingRequestCommand.RESERVE_NOW,
error as Error,
- { errorResponse: OCPP16Constants.OCPP_RESERVATION_RESPONSE_FAULTED },
- )!;
+ { errorResponse: OCPP16Constants.OCPP_RESERVATION_RESPONSE_FAULTED }
+ )!
}
}
- private async handleRequestCancelReservation(
+ private async handleRequestCancelReservation (
chargingStation: ChargingStation,
- commandPayload: OCPP16CancelReservationRequest,
+ commandPayload: OCPP16CancelReservationRequest
): Promise<GenericResponse> {
if (
!OCPP16ServiceUtils.checkFeatureProfile(
chargingStation,
OCPP16SupportedFeatureProfiles.Reservation,
- OCPP16IncomingRequestCommand.CANCEL_RESERVATION,
+ OCPP16IncomingRequestCommand.CANCEL_RESERVATION
)
) {
- return OCPP16Constants.OCPP_CANCEL_RESERVATION_RESPONSE_REJECTED;
+ return OCPP16Constants.OCPP_CANCEL_RESERVATION_RESPONSE_REJECTED
}
try {
- const { reservationId } = commandPayload;
- const reservation = chargingStation.getReservationBy('reservationId', reservationId);
+ const { reservationId } = commandPayload
+ const reservation = chargingStation.getReservationBy('reservationId', reservationId)
if (isUndefined(reservation)) {
logger.debug(
- `${chargingStation.logPrefix()} Reservation with id ${reservationId} does not exist on charging station`,
- );
- return OCPP16Constants.OCPP_CANCEL_RESERVATION_RESPONSE_REJECTED;
+ `${chargingStation.logPrefix()} Reservation with id ${reservationId} does not exist on charging station`
+ )
+ return OCPP16Constants.OCPP_CANCEL_RESERVATION_RESPONSE_REJECTED
}
await chargingStation.removeReservation(
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
reservation!,
- ReservationTerminationReason.RESERVATION_CANCELED,
- );
- return OCPP16Constants.OCPP_CANCEL_RESERVATION_RESPONSE_ACCEPTED;
+ ReservationTerminationReason.RESERVATION_CANCELED
+ )
+ return OCPP16Constants.OCPP_CANCEL_RESERVATION_RESPONSE_ACCEPTED
} catch (error) {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
return this.handleIncomingRequestError<GenericResponse>(
chargingStation,
OCPP16IncomingRequestCommand.CANCEL_RESERVATION,
error as Error,
- { errorResponse: OCPP16Constants.OCPP_CANCEL_RESERVATION_RESPONSE_REJECTED },
- )!;
+ { errorResponse: OCPP16Constants.OCPP_CANCEL_RESERVATION_RESPONSE_REJECTED }
+ )!
}
}
}
// Partial Copyright Jerome Benoit. 2021-2023. All Rights Reserved.
-import type { JSONSchemaType } from 'ajv';
+import type { JSONSchemaType } from 'ajv'
-import { OCPP16Constants } from './OCPP16Constants.js';
-import { OCPP16ServiceUtils } from './OCPP16ServiceUtils.js';
-import type { ChargingStation } from '../../../charging-station/index.js';
-import { OCPPError } from '../../../exception/index.js';
+import { OCPP16Constants } from './OCPP16Constants.js'
+import { OCPP16ServiceUtils } from './OCPP16ServiceUtils.js'
+import type { ChargingStation } from '../../../charging-station/index.js'
+import { OCPPError } from '../../../exception/index.js'
import {
ErrorType,
type JsonObject,
type OCPP16StatusNotificationRequest,
type OCPP16StopTransactionRequest,
OCPPVersion,
- type RequestParams,
-} from '../../../types/index.js';
-import { Constants, generateUUID } from '../../../utils/index.js';
-import { OCPPRequestService } from '../OCPPRequestService.js';
-import type { OCPPResponseService } from '../OCPPResponseService.js';
+ type RequestParams
+} from '../../../types/index.js'
+import { Constants, generateUUID } from '../../../utils/index.js'
+import { OCPPRequestService } from '../OCPPRequestService.js'
+import type { OCPPResponseService } from '../OCPPResponseService.js'
-const moduleName = 'OCPP16RequestService';
+const moduleName = 'OCPP16RequestService'
export class OCPP16RequestService extends OCPPRequestService {
- protected jsonSchemas: Map<OCPP16RequestCommand, JSONSchemaType<JsonType>>;
+ protected jsonSchemas: Map<OCPP16RequestCommand, JSONSchemaType<JsonType>>
- public constructor(ocppResponseService: OCPPResponseService) {
+ public constructor (ocppResponseService: OCPPResponseService) {
// if (new.target?.name === moduleName) {
- // throw new TypeError(`Cannot construct ${new.target?.name} instances directly`);
+ // throw new TypeError(`Cannot construct ${new.target?.name} instances directly`)
// }
- super(OCPPVersion.VERSION_16, ocppResponseService);
+ super(OCPPVersion.VERSION_16, ocppResponseService)
this.jsonSchemas = new Map<OCPP16RequestCommand, JSONSchemaType<JsonType>>([
[
OCPP16RequestCommand.AUTHORIZE,
OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16AuthorizeRequest>(
'assets/json-schemas/ocpp/1.6/Authorize.json',
moduleName,
- 'constructor',
- ),
+ 'constructor'
+ )
],
[
OCPP16RequestCommand.BOOT_NOTIFICATION,
OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16BootNotificationRequest>(
'assets/json-schemas/ocpp/1.6/BootNotification.json',
moduleName,
- 'constructor',
- ),
+ 'constructor'
+ )
],
[
OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION,
OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16DiagnosticsStatusNotificationRequest>(
'assets/json-schemas/ocpp/1.6/DiagnosticsStatusNotification.json',
moduleName,
- 'constructor',
- ),
+ 'constructor'
+ )
],
[
OCPP16RequestCommand.HEARTBEAT,
OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16HeartbeatRequest>(
'assets/json-schemas/ocpp/1.6/Heartbeat.json',
moduleName,
- 'constructor',
- ),
+ 'constructor'
+ )
],
[
OCPP16RequestCommand.METER_VALUES,
OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16MeterValuesRequest>(
'assets/json-schemas/ocpp/1.6/MeterValues.json',
moduleName,
- 'constructor',
- ),
+ 'constructor'
+ )
],
[
OCPP16RequestCommand.STATUS_NOTIFICATION,
OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16StatusNotificationRequest>(
'assets/json-schemas/ocpp/1.6/StatusNotification.json',
moduleName,
- 'constructor',
- ),
+ 'constructor'
+ )
],
[
OCPP16RequestCommand.START_TRANSACTION,
OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16StartTransactionRequest>(
'assets/json-schemas/ocpp/1.6/StartTransaction.json',
moduleName,
- 'constructor',
- ),
+ 'constructor'
+ )
],
[
OCPP16RequestCommand.STOP_TRANSACTION,
OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16StopTransactionRequest>(
'assets/json-schemas/ocpp/1.6/StopTransaction.json',
moduleName,
- 'constructor',
- ),
+ 'constructor'
+ )
],
[
OCPP16RequestCommand.DATA_TRANSFER,
OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16DataTransferRequest>(
'assets/json-schemas/ocpp/1.6/DataTransfer.json',
moduleName,
- 'constructor',
- ),
+ 'constructor'
+ )
],
[
OCPP16RequestCommand.FIRMWARE_STATUS_NOTIFICATION,
OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16FirmwareStatusNotificationRequest>(
'assets/json-schemas/ocpp/1.6/FirmwareStatusNotification.json',
moduleName,
- 'constructor',
- ),
- ],
- ]);
+ 'constructor'
+ )
+ ]
+ ])
this.buildRequestPayload = this.buildRequestPayload.bind(this) as <Request extends JsonType>(
chargingStation: ChargingStation,
commandName: OCPP16RequestCommand,
- commandParams?: JsonType,
- ) => Request;
+ commandParams?: JsonType
+ ) => Request
}
public async requestHandler<RequestType extends JsonType, ResponseType extends JsonType>(
chargingStation: ChargingStation,
commandName: OCPP16RequestCommand,
commandParams?: JsonType,
- params?: RequestParams,
+ params?: RequestParams
): Promise<ResponseType> {
// FIXME?: add sanity checks on charging station availability, connector availability, connector status, etc.
- if (OCPP16ServiceUtils.isRequestCommandSupported(chargingStation, commandName) === true) {
+ if (OCPP16ServiceUtils.isRequestCommandSupported(chargingStation, commandName)) {
return (await this.sendMessage(
chargingStation,
generateUUID(),
this.buildRequestPayload<RequestType>(chargingStation, commandName, commandParams),
commandName,
- params,
- )) as ResponseType;
+ params
+ )) as ResponseType
}
// OCPPError usage here is debatable: it's an error in the OCPP stack but not targeted to sendError().
throw new OCPPError(
ErrorType.NOT_SUPPORTED,
`Unsupported OCPP command '${commandName}'`,
commandName,
- commandParams,
- );
+ commandParams
+ )
}
private buildRequestPayload<Request extends JsonType>(
chargingStation: ChargingStation,
commandName: OCPP16RequestCommand,
- commandParams?: JsonType,
+ commandParams?: JsonType
): Request {
- let connectorId: number | undefined;
- let energyActiveImportRegister: number;
- commandParams = commandParams as JsonObject;
+ let connectorId: number | undefined
+ let energyActiveImportRegister: number
+ commandParams = commandParams as JsonObject
switch (commandName) {
case OCPP16RequestCommand.BOOT_NOTIFICATION:
case OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION:
case OCPP16RequestCommand.METER_VALUES:
case OCPP16RequestCommand.STATUS_NOTIFICATION:
case OCPP16RequestCommand.DATA_TRANSFER:
- return commandParams as unknown as Request;
+ return commandParams as unknown as Request
case OCPP16RequestCommand.AUTHORIZE:
return {
idTag: Constants.DEFAULT_IDTAG,
- ...commandParams,
- } as unknown as Request;
+ ...commandParams
+ } as unknown as Request
case OCPP16RequestCommand.HEARTBEAT:
- return OCPP16Constants.OCPP_REQUEST_EMPTY as unknown as Request;
+ return OCPP16Constants.OCPP_REQUEST_EMPTY as unknown as Request
case OCPP16RequestCommand.START_TRANSACTION:
return {
idTag: Constants.DEFAULT_IDTAG,
meterStart: chargingStation.getEnergyActiveImportRegisterByConnectorId(
commandParams?.connectorId as number,
- true,
+ true
),
timestamp: new Date(),
...(OCPP16ServiceUtils.hasReservation(
chargingStation,
commandParams?.connectorId as number,
- commandParams?.idTag as string,
+ commandParams?.idTag as string
) && {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
reservationId: chargingStation.getReservationBy(
'connectorId',
chargingStation.getConnectorStatus(0)?.status === OCPP16ChargePointStatus.Reserved
? 0
- : (commandParams?.connectorId as number),
- )!.reservationId,
+ : (commandParams?.connectorId as number)
+ )!.reservationId
}),
- ...commandParams,
- } as unknown as Request;
+ ...commandParams
+ } as unknown as Request
case OCPP16RequestCommand.STOP_TRANSACTION:
- chargingStation.stationInfo?.transactionDataMeterValues &&
+ chargingStation.stationInfo?.transactionDataMeterValues === true &&
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
(connectorId = chargingStation.getConnectorIdByTransactionId(
- commandParams?.transactionId as number,
- )!);
+ commandParams?.transactionId as number
+ )!)
energyActiveImportRegister = chargingStation.getEnergyActiveImportRegisterByTransactionId(
commandParams?.transactionId as number,
- true,
- );
+ true
+ )
return {
idTag: chargingStation.getTransactionIdTag(commandParams?.transactionId as number),
meterStop: energyActiveImportRegister,
timestamp: new Date(),
- ...(chargingStation.stationInfo?.transactionDataMeterValues && {
+ ...(chargingStation.stationInfo?.transactionDataMeterValues === true && {
transactionData: OCPP16ServiceUtils.buildTransactionDataMeterValues(
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
chargingStation.getConnectorStatus(connectorId!)!.transactionBeginMeterValue!,
OCPP16ServiceUtils.buildTransactionEndMeterValue(
chargingStation,
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
connectorId!,
- energyActiveImportRegister,
- ),
- ),
+ energyActiveImportRegister
+ )
+ )
}),
- ...commandParams,
- } as unknown as Request;
+ ...commandParams
+ } as unknown as Request
default:
// OCPPError usage here is debatable: it's an error in the OCPP stack but not targeted to sendError().
throw new OCPPError(
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
`Unsupported OCPP command '${commandName}'`,
commandName,
- commandParams,
- );
+ commandParams
+ )
}
}
}
// Partial Copyright Jerome Benoit. 2021-2023. All Rights Reserved.
-import type { JSONSchemaType } from 'ajv';
-import { secondsToMilliseconds } from 'date-fns';
+import type { JSONSchemaType } from 'ajv'
+import { secondsToMilliseconds } from 'date-fns'
-import { OCPP16ServiceUtils } from './OCPP16ServiceUtils.js';
+import { OCPP16ServiceUtils } from './OCPP16ServiceUtils.js'
import {
type ChargingStation,
addConfigurationKey,
getConfigurationKey,
hasReservationExpired,
- resetConnectorStatus,
-} from '../../../charging-station/index.js';
-import { OCPPError } from '../../../exception/index.js';
+ resetConnectorStatus
+} from '../../../charging-station/index.js'
+import { OCPPError } from '../../../exception/index.js'
import {
type ChangeConfigurationResponse,
ErrorType,
ReservationTerminationReason,
type ResponseHandler,
type SetChargingProfileResponse,
- type UnlockConnectorResponse,
-} from '../../../types/index.js';
-import { Constants, convertToInt, isNullOrUndefined, logger } from '../../../utils/index.js';
-import { OCPPResponseService } from '../OCPPResponseService.js';
+ type UnlockConnectorResponse
+} from '../../../types/index.js'
+import { Constants, convertToInt, isNullOrUndefined, logger } from '../../../utils/index.js'
+import { OCPPResponseService } from '../OCPPResponseService.js'
-const moduleName = 'OCPP16ResponseService';
+const moduleName = 'OCPP16ResponseService'
export class OCPP16ResponseService extends OCPPResponseService {
public jsonIncomingRequestResponseSchemas: Map<
- OCPP16IncomingRequestCommand,
- JSONSchemaType<JsonType>
- >;
+ OCPP16IncomingRequestCommand,
+ JSONSchemaType<JsonType>
+ >
- private responseHandlers: Map<OCPP16RequestCommand, ResponseHandler>;
- private jsonSchemas: Map<OCPP16RequestCommand, JSONSchemaType<JsonType>>;
+ private readonly responseHandlers: Map<OCPP16RequestCommand, ResponseHandler>
+ private readonly jsonSchemas: Map<OCPP16RequestCommand, JSONSchemaType<JsonType>>
- public constructor() {
+ public constructor () {
// if (new.target?.name === moduleName) {
- // throw new TypeError(`Cannot construct ${new.target?.name} instances directly`);
+ // throw new TypeError(`Cannot construct ${new.target?.name} instances directly`)
// }
- super(OCPPVersion.VERSION_16);
+ super(OCPPVersion.VERSION_16)
this.responseHandlers = new Map<OCPP16RequestCommand, ResponseHandler>([
[
OCPP16RequestCommand.BOOT_NOTIFICATION,
- this.handleResponseBootNotification.bind(this) as ResponseHandler,
+ this.handleResponseBootNotification.bind(this) as ResponseHandler
],
[OCPP16RequestCommand.HEARTBEAT, this.emptyResponseHandler.bind(this) as ResponseHandler],
[OCPP16RequestCommand.AUTHORIZE, this.handleResponseAuthorize.bind(this) as ResponseHandler],
[
OCPP16RequestCommand.START_TRANSACTION,
- this.handleResponseStartTransaction.bind(this) as ResponseHandler,
+ this.handleResponseStartTransaction.bind(this) as ResponseHandler
],
[
OCPP16RequestCommand.STOP_TRANSACTION,
- this.handleResponseStopTransaction.bind(this) as ResponseHandler,
+ this.handleResponseStopTransaction.bind(this) as ResponseHandler
],
[
OCPP16RequestCommand.STATUS_NOTIFICATION,
- this.emptyResponseHandler.bind(this) as ResponseHandler,
+ this.emptyResponseHandler.bind(this) as ResponseHandler
],
[OCPP16RequestCommand.METER_VALUES, this.emptyResponseHandler.bind(this) as ResponseHandler],
[
OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION,
- this.emptyResponseHandler.bind(this) as ResponseHandler,
+ this.emptyResponseHandler.bind(this) as ResponseHandler
],
[OCPP16RequestCommand.DATA_TRANSFER, this.emptyResponseHandler.bind(this) as ResponseHandler],
[
OCPP16RequestCommand.FIRMWARE_STATUS_NOTIFICATION,
- this.emptyResponseHandler.bind(this) as ResponseHandler,
- ],
- ]);
+ this.emptyResponseHandler.bind(this) as ResponseHandler
+ ]
+ ])
this.jsonSchemas = new Map<OCPP16RequestCommand, JSONSchemaType<JsonType>>([
[
OCPP16RequestCommand.BOOT_NOTIFICATION,
OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16BootNotificationResponse>(
'assets/json-schemas/ocpp/1.6/BootNotificationResponse.json',
moduleName,
- 'constructor',
- ),
+ 'constructor'
+ )
],
[
OCPP16RequestCommand.HEARTBEAT,
OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16HeartbeatResponse>(
'assets/json-schemas/ocpp/1.6/HeartbeatResponse.json',
moduleName,
- 'constructor',
- ),
+ 'constructor'
+ )
],
[
OCPP16RequestCommand.AUTHORIZE,
OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16AuthorizeResponse>(
'assets/json-schemas/ocpp/1.6/AuthorizeResponse.json',
moduleName,
- 'constructor',
- ),
+ 'constructor'
+ )
],
[
OCPP16RequestCommand.START_TRANSACTION,
OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16StartTransactionResponse>(
'assets/json-schemas/ocpp/1.6/StartTransactionResponse.json',
moduleName,
- 'constructor',
- ),
+ 'constructor'
+ )
],
[
OCPP16RequestCommand.STOP_TRANSACTION,
OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16StopTransactionResponse>(
'assets/json-schemas/ocpp/1.6/StopTransactionResponse.json',
moduleName,
- 'constructor',
- ),
+ 'constructor'
+ )
],
[
OCPP16RequestCommand.STATUS_NOTIFICATION,
OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16StatusNotificationResponse>(
'assets/json-schemas/ocpp/1.6/StatusNotificationResponse.json',
moduleName,
- 'constructor',
- ),
+ 'constructor'
+ )
],
[
OCPP16RequestCommand.METER_VALUES,
OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16MeterValuesResponse>(
'assets/json-schemas/ocpp/1.6/MeterValuesResponse.json',
moduleName,
- 'constructor',
- ),
+ 'constructor'
+ )
],
[
OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION,
OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16DiagnosticsStatusNotificationResponse>(
'assets/json-schemas/ocpp/1.6/DiagnosticsStatusNotificationResponse.json',
moduleName,
- 'constructor',
- ),
+ 'constructor'
+ )
],
[
OCPP16RequestCommand.DATA_TRANSFER,
OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16DataTransferResponse>(
'assets/json-schemas/ocpp/1.6/DataTransferResponse.json',
moduleName,
- 'constructor',
- ),
+ 'constructor'
+ )
],
[
OCPP16RequestCommand.FIRMWARE_STATUS_NOTIFICATION,
OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16FirmwareStatusNotificationResponse>(
'assets/json-schemas/ocpp/1.6/FirmwareStatusNotificationResponse.json',
moduleName,
- 'constructor',
- ),
- ],
- ]);
+ 'constructor'
+ )
+ ]
+ ])
this.jsonIncomingRequestResponseSchemas = new Map([
[
OCPP16IncomingRequestCommand.RESET,
OCPP16ServiceUtils.parseJsonSchemaFile<GenericResponse>(
'assets/json-schemas/ocpp/1.6/ResetResponse.json',
moduleName,
- 'constructor',
- ),
+ 'constructor'
+ )
],
[
OCPP16IncomingRequestCommand.CLEAR_CACHE,
OCPP16ServiceUtils.parseJsonSchemaFile<GenericResponse>(
'assets/json-schemas/ocpp/1.6/ClearCacheResponse.json',
moduleName,
- 'constructor',
- ),
+ 'constructor'
+ )
],
[
OCPP16IncomingRequestCommand.CHANGE_AVAILABILITY,
OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16ChangeAvailabilityResponse>(
'assets/json-schemas/ocpp/1.6/ChangeAvailabilityResponse.json',
moduleName,
- 'constructor',
- ),
+ 'constructor'
+ )
],
[
OCPP16IncomingRequestCommand.UNLOCK_CONNECTOR,
OCPP16ServiceUtils.parseJsonSchemaFile<UnlockConnectorResponse>(
'assets/json-schemas/ocpp/1.6/UnlockConnectorResponse.json',
moduleName,
- 'constructor',
- ),
+ 'constructor'
+ )
],
[
OCPP16IncomingRequestCommand.GET_CONFIGURATION,
OCPP16ServiceUtils.parseJsonSchemaFile<GetConfigurationResponse>(
'assets/json-schemas/ocpp/1.6/GetConfigurationResponse.json',
moduleName,
- 'constructor',
- ),
+ 'constructor'
+ )
],
[
OCPP16IncomingRequestCommand.CHANGE_CONFIGURATION,
OCPP16ServiceUtils.parseJsonSchemaFile<ChangeConfigurationResponse>(
'assets/json-schemas/ocpp/1.6/ChangeConfigurationResponse.json',
moduleName,
- 'constructor',
- ),
+ 'constructor'
+ )
],
[
OCPP16IncomingRequestCommand.GET_COMPOSITE_SCHEDULE,
OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16GetCompositeScheduleResponse>(
'assets/json-schemas/ocpp/1.6/GetCompositeScheduleResponse.json',
moduleName,
- 'constructor',
- ),
+ 'constructor'
+ )
],
[
OCPP16IncomingRequestCommand.SET_CHARGING_PROFILE,
OCPP16ServiceUtils.parseJsonSchemaFile<SetChargingProfileResponse>(
'assets/json-schemas/ocpp/1.6/SetChargingProfileResponse.json',
moduleName,
- 'constructor',
- ),
+ 'constructor'
+ )
],
[
OCPP16IncomingRequestCommand.CLEAR_CHARGING_PROFILE,
OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16ClearChargingProfileResponse>(
'assets/json-schemas/ocpp/1.6/ClearChargingProfileResponse.json',
moduleName,
- 'constructor',
- ),
+ 'constructor'
+ )
],
[
OCPP16IncomingRequestCommand.REMOTE_START_TRANSACTION,
OCPP16ServiceUtils.parseJsonSchemaFile<GenericResponse>(
'assets/json-schemas/ocpp/1.6/RemoteStartTransactionResponse.json',
moduleName,
- 'constructor',
- ),
+ 'constructor'
+ )
],
[
OCPP16IncomingRequestCommand.REMOTE_STOP_TRANSACTION,
OCPP16ServiceUtils.parseJsonSchemaFile<GenericResponse>(
'assets/json-schemas/ocpp/1.6/RemoteStopTransactionResponse.json',
moduleName,
- 'constructor',
- ),
+ 'constructor'
+ )
],
[
OCPP16IncomingRequestCommand.GET_DIAGNOSTICS,
OCPP16ServiceUtils.parseJsonSchemaFile<GetDiagnosticsResponse>(
'assets/json-schemas/ocpp/1.6/GetDiagnosticsResponse.json',
moduleName,
- 'constructor',
- ),
+ 'constructor'
+ )
],
[
OCPP16IncomingRequestCommand.TRIGGER_MESSAGE,
OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16TriggerMessageResponse>(
'assets/json-schemas/ocpp/1.6/TriggerMessageResponse.json',
moduleName,
- 'constructor',
- ),
+ 'constructor'
+ )
],
[
OCPP16IncomingRequestCommand.DATA_TRANSFER,
OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16DataTransferResponse>(
'assets/json-schemas/ocpp/1.6/DataTransferResponse.json',
moduleName,
- 'constructor',
- ),
+ 'constructor'
+ )
],
[
OCPP16IncomingRequestCommand.UPDATE_FIRMWARE,
OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16UpdateFirmwareResponse>(
'assets/json-schemas/ocpp/1.6/UpdateFirmwareResponse.json',
moduleName,
- 'constructor',
- ),
+ 'constructor'
+ )
],
[
OCPP16IncomingRequestCommand.RESERVE_NOW,
OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16ReserveNowResponse>(
'assets/json-schemas/ocpp/1.6/ReserveNowResponse.json',
moduleName,
- 'constructor',
- ),
+ 'constructor'
+ )
],
[
OCPP16IncomingRequestCommand.CANCEL_RESERVATION,
OCPP16ServiceUtils.parseJsonSchemaFile<GenericResponse>(
'assets/json-schemas/ocpp/1.6/CancelReservationResponse.json',
moduleName,
- 'constructor',
- ),
- ],
- ]);
+ 'constructor'
+ )
+ ]
+ ])
this.validatePayload = this.validatePayload.bind(this) as (
chargingStation: ChargingStation,
commandName: OCPP16RequestCommand,
- payload: JsonType,
- ) => boolean;
+ payload: JsonType
+ ) => boolean
}
public async responseHandler<ReqType extends JsonType, ResType extends JsonType>(
chargingStation: ChargingStation,
commandName: OCPP16RequestCommand,
payload: ResType,
- requestPayload: ReqType,
+ requestPayload: ReqType
): Promise<void> {
- if (
- chargingStation.isRegistered() === true ||
- commandName === OCPP16RequestCommand.BOOT_NOTIFICATION
- ) {
+ if (chargingStation.isRegistered() || commandName === OCPP16RequestCommand.BOOT_NOTIFICATION) {
if (
- this.responseHandlers.has(commandName) === true &&
- OCPP16ServiceUtils.isRequestCommandSupported(chargingStation, commandName) === true
+ this.responseHandlers.has(commandName) &&
+ OCPP16ServiceUtils.isRequestCommandSupported(chargingStation, commandName)
) {
try {
- this.validatePayload(chargingStation, commandName, payload);
- await this.responseHandlers.get(commandName)!(chargingStation, payload, requestPayload);
+ this.validatePayload(chargingStation, commandName, payload)
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ await this.responseHandlers.get(commandName)!(chargingStation, payload, requestPayload)
} catch (error) {
logger.error(
`${chargingStation.logPrefix()} ${moduleName}.responseHandler: Handle response error:`,
- error,
- );
- throw error;
+ error
+ )
+ throw error
}
} else {
// Throw exception
`${commandName} is not implemented to handle response PDU ${JSON.stringify(
payload,
undefined,
- 2,
+ 2
)}`,
commandName,
- payload,
- );
+ payload
+ )
}
} else {
throw new OCPPError(
`${commandName} cannot be issued to handle response PDU ${JSON.stringify(
payload,
undefined,
- 2,
+ 2
)} while the charging station is not registered on the central server.`,
commandName,
- payload,
- );
+ payload
+ )
}
}
- private validatePayload(
+ private validatePayload (
chargingStation: ChargingStation,
commandName: OCPP16RequestCommand,
- payload: JsonType,
+ payload: JsonType
): boolean {
- if (this.jsonSchemas.has(commandName) === true) {
+ if (this.jsonSchemas.has(commandName)) {
return this.validateResponsePayload(
chargingStation,
commandName,
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.jsonSchemas.get(commandName)!,
- payload,
- );
+ payload
+ )
}
logger.warn(
- `${chargingStation.logPrefix()} ${moduleName}.validatePayload: No JSON schema found for command '${commandName}' PDU validation`,
- );
- return false;
+ `${chargingStation.logPrefix()} ${moduleName}.validatePayload: No JSON schema found for command '${commandName}' PDU validation`
+ )
+ return false
}
- private handleResponseBootNotification(
+ private handleResponseBootNotification (
chargingStation: ChargingStation,
- payload: OCPP16BootNotificationResponse,
+ payload: OCPP16BootNotificationResponse
): void {
if (payload.status === RegistrationStatusEnumType.ACCEPTED) {
addConfigurationKey(
OCPP16StandardParametersKey.HeartbeatInterval,
payload.interval.toString(),
{},
- { overwrite: true, save: true },
- );
+ { overwrite: true, save: true }
+ )
addConfigurationKey(
chargingStation,
OCPP16StandardParametersKey.HeartBeatInterval,
payload.interval.toString(),
{ visible: false },
- { overwrite: true, save: true },
- );
- OCPP16ServiceUtils.startHeartbeatInterval(chargingStation, payload.interval);
+ { overwrite: true, save: true }
+ )
+ OCPP16ServiceUtils.startHeartbeatInterval(chargingStation, payload.interval)
}
if (Object.values(RegistrationStatusEnumType).includes(payload.status)) {
const logMsg = `${chargingStation.logPrefix()} Charging station in '${
payload.status
- }' state on the central server`;
+ }' state on the central server`
payload.status === RegistrationStatusEnumType.REJECTED
? logger.warn(logMsg)
- : logger.info(logMsg);
+ : logger.info(logMsg)
} else {
logger.error(
`${chargingStation.logPrefix()} Charging station boot notification response received: %j with undefined registration status`,
- payload,
- );
+ payload
+ )
}
}
- private handleResponseAuthorize(
+ private handleResponseAuthorize (
chargingStation: ChargingStation,
payload: OCPP16AuthorizeResponse,
- requestPayload: OCPP16AuthorizeRequest,
+ requestPayload: OCPP16AuthorizeRequest
): void {
- let authorizeConnectorId: number | undefined;
+ let authorizeConnectorId: number | undefined
if (chargingStation.hasEvses) {
for (const [evseId, evseStatus] of chargingStation.evses) {
if (evseId > 0) {
for (const [connectorId, connectorStatus] of evseStatus.connectors) {
if (connectorStatus?.authorizeIdTag === requestPayload.idTag) {
- authorizeConnectorId = connectorId;
- break;
+ authorizeConnectorId = connectorId
+ break
}
}
}
connectorId > 0 &&
chargingStation.getConnectorStatus(connectorId)?.authorizeIdTag === requestPayload.idTag
) {
- authorizeConnectorId = connectorId;
- break;
+ authorizeConnectorId = connectorId
+ break
}
}
}
- const authorizeConnectorStatus = chargingStation.getConnectorStatus(authorizeConnectorId!);
- const authorizeConnectorIdDefined = !isNullOrUndefined(authorizeConnectorId);
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ const authorizeConnectorStatus = chargingStation.getConnectorStatus(authorizeConnectorId!)
+ const authorizeConnectorIdDefined = !isNullOrUndefined(authorizeConnectorId)
if (payload.idTagInfo.status === OCPP16AuthorizationStatus.ACCEPTED) {
if (authorizeConnectorIdDefined) {
- // authorizeConnectorStatus!.authorizeIdTag = requestPayload.idTag;
- authorizeConnectorStatus!.idTagAuthorized = true;
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ authorizeConnectorStatus!.idTagAuthorized = true
}
logger.debug(
`${chargingStation.logPrefix()} idTag '${requestPayload.idTag}' accepted${
authorizeConnectorIdDefined ? ` on connector id ${authorizeConnectorId}` : ''
- }`,
- );
+ }`
+ )
} else {
if (authorizeConnectorIdDefined) {
- authorizeConnectorStatus!.idTagAuthorized = false;
- delete authorizeConnectorStatus?.authorizeIdTag;
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ authorizeConnectorStatus!.idTagAuthorized = false
+ delete authorizeConnectorStatus?.authorizeIdTag
}
logger.debug(
`${chargingStation.logPrefix()} idTag '${requestPayload.idTag}' rejected with status '${
payload.idTagInfo.status
- }'${authorizeConnectorIdDefined ? ` on connector id ${authorizeConnectorId}` : ''}`,
- );
+ }'${authorizeConnectorIdDefined ? ` on connector id ${authorizeConnectorId}` : ''}`
+ )
}
}
- private async handleResponseStartTransaction(
+ private async handleResponseStartTransaction (
chargingStation: ChargingStation,
payload: OCPP16StartTransactionResponse,
- requestPayload: OCPP16StartTransactionRequest,
+ requestPayload: OCPP16StartTransactionRequest
): Promise<void> {
- const { connectorId } = requestPayload;
- if (connectorId === 0 || chargingStation.hasConnector(connectorId) === false) {
+ const { connectorId } = requestPayload
+ if (connectorId === 0 || !chargingStation.hasConnector(connectorId)) {
logger.error(
- `${chargingStation.logPrefix()} Trying to start a transaction on a non existing connector id ${connectorId}`,
- );
- return;
+ `${chargingStation.logPrefix()} Trying to start a transaction on a non existing connector id ${connectorId}`
+ )
+ return
}
- const connectorStatus = chargingStation.getConnectorStatus(connectorId);
+ const connectorStatus = chargingStation.getConnectorStatus(connectorId)
if (
connectorStatus?.transactionRemoteStarted === true &&
- chargingStation.getAuthorizeRemoteTxRequests() === true &&
- chargingStation.getLocalAuthListEnabled() === true &&
- chargingStation.hasIdTags() === true &&
+ chargingStation.getAuthorizeRemoteTxRequests() &&
+ chargingStation.getLocalAuthListEnabled() &&
+ chargingStation.hasIdTags() &&
connectorStatus?.idTagLocalAuthorized === false
) {
logger.error(
- `${chargingStation.logPrefix()} Trying to start a transaction with a not local authorized idTag ${connectorStatus?.localAuthorizeIdTag} on connector id ${connectorId}`,
- );
- await this.resetConnectorOnStartTransactionError(chargingStation, connectorId);
- return;
+ `${chargingStation.logPrefix()} Trying to start a transaction with a not local authorized idTag ${connectorStatus?.localAuthorizeIdTag} on connector id ${connectorId}`
+ )
+ await this.resetConnectorOnStartTransactionError(chargingStation, connectorId)
+ return
}
if (
connectorStatus?.transactionRemoteStarted === true &&
- chargingStation.getAuthorizeRemoteTxRequests() === true &&
+ chargingStation.getAuthorizeRemoteTxRequests() &&
chargingStation.stationInfo?.remoteAuthorization === true &&
connectorStatus?.idTagLocalAuthorized === false &&
connectorStatus?.idTagAuthorized === false
) {
logger.error(
- `${chargingStation.logPrefix()} Trying to start a transaction with a not authorized idTag ${connectorStatus?.authorizeIdTag} on connector id ${connectorId}`,
- );
- await this.resetConnectorOnStartTransactionError(chargingStation, connectorId);
- return;
+ `${chargingStation.logPrefix()} Trying to start a transaction with a not authorized idTag ${connectorStatus?.authorizeIdTag} on connector id ${connectorId}`
+ )
+ await this.resetConnectorOnStartTransactionError(chargingStation, connectorId)
+ return
}
if (
- connectorStatus?.idTagAuthorized &&
+ connectorStatus?.idTagAuthorized === true &&
connectorStatus?.authorizeIdTag !== requestPayload.idTag
) {
logger.error(
`${chargingStation.logPrefix()} Trying to start a transaction with an idTag ${
requestPayload.idTag
- } different from the authorize request one ${connectorStatus?.authorizeIdTag} on connector id ${connectorId}`,
- );
- await this.resetConnectorOnStartTransactionError(chargingStation, connectorId);
- return;
+ } different from the authorize request one ${connectorStatus?.authorizeIdTag} on connector id ${connectorId}`
+ )
+ await this.resetConnectorOnStartTransactionError(chargingStation, connectorId)
+ return
}
if (
- connectorStatus?.idTagLocalAuthorized &&
+ connectorStatus?.idTagLocalAuthorized === true &&
connectorStatus?.localAuthorizeIdTag !== requestPayload.idTag
) {
logger.error(
`${chargingStation.logPrefix()} Trying to start a transaction with an idTag ${
requestPayload.idTag
- } different from the local authorized one ${connectorStatus?.localAuthorizeIdTag} on connector id ${connectorId}`,
- );
- await this.resetConnectorOnStartTransactionError(chargingStation, connectorId);
- return;
+ } different from the local authorized one ${connectorStatus?.localAuthorizeIdTag} on connector id ${connectorId}`
+ )
+ await this.resetConnectorOnStartTransactionError(chargingStation, connectorId)
+ return
}
if (connectorStatus?.transactionStarted === true) {
logger.error(
- `${chargingStation.logPrefix()} Trying to start a transaction on an already used connector id ${connectorId} by idTag ${connectorStatus?.transactionIdTag}`,
- );
- return;
+ `${chargingStation.logPrefix()} Trying to start a transaction on an already used connector id ${connectorId} by idTag ${connectorStatus?.transactionIdTag}`
+ )
+ return
}
if (chargingStation.hasEvses) {
for (const [evseId, evseStatus] of chargingStation.evses) {
for (const [id, status] of evseStatus.connectors) {
if (id !== connectorId && status?.transactionStarted === true) {
logger.error(
- `${chargingStation.logPrefix()} Trying to start a transaction on an already used evse id ${evseId} by connector id ${id} with idTag ${status?.transactionIdTag}`,
- );
- await this.resetConnectorOnStartTransactionError(chargingStation, connectorId);
- return;
+ `${chargingStation.logPrefix()} Trying to start a transaction on an already used evse id ${evseId} by connector id ${id} with idTag ${status?.transactionIdTag}`
+ )
+ await this.resetConnectorOnStartTransactionError(chargingStation, connectorId)
+ return
}
}
}
connectorStatus?.status !== OCPP16ChargePointStatus.Preparing
) {
logger.error(
- `${chargingStation.logPrefix()} Trying to start a transaction on connector id ${connectorId} with status ${connectorStatus?.status}`,
- );
- return;
+ `${chargingStation.logPrefix()} Trying to start a transaction on connector id ${connectorId} with status ${connectorStatus?.status}`
+ )
+ return
}
if (!Number.isSafeInteger(payload.transactionId)) {
logger.warn(
`${chargingStation.logPrefix()} Trying to start a transaction on connector id ${connectorId} with a non integer transaction id ${
payload.transactionId
- }, converting to integer`,
- );
- payload.transactionId = convertToInt(payload.transactionId);
+ }, converting to integer`
+ )
+ payload.transactionId = convertToInt(payload.transactionId)
}
if (payload.idTagInfo?.status === OCPP16AuthorizationStatus.ACCEPTED) {
- connectorStatus.transactionStarted = true;
- connectorStatus.transactionStart = requestPayload.timestamp;
- connectorStatus.transactionId = payload.transactionId;
- connectorStatus.transactionIdTag = requestPayload.idTag;
- connectorStatus.transactionEnergyActiveImportRegisterValue = 0;
+ connectorStatus.transactionStarted = true
+ connectorStatus.transactionStart = requestPayload.timestamp
+ connectorStatus.transactionId = payload.transactionId
+ connectorStatus.transactionIdTag = requestPayload.idTag
+ connectorStatus.transactionEnergyActiveImportRegisterValue = 0
connectorStatus.transactionBeginMeterValue =
OCPP16ServiceUtils.buildTransactionBeginMeterValue(
chargingStation,
connectorId,
- requestPayload.meterStart,
- );
- if (requestPayload.reservationId) {
+ requestPayload.meterStart
+ )
+ if (requestPayload.reservationId != null) {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const reservation = chargingStation.getReservationBy(
'reservationId',
- requestPayload.reservationId,
- )!;
+ requestPayload.reservationId
+ )!
if (reservation.idTag !== requestPayload.idTag) {
logger.warn(
`${chargingStation.logPrefix()} Reserved transaction ${
payload.transactionId
} started with a different idTag ${requestPayload.idTag} than the reservation one ${
reservation.idTag
- }`,
- );
+ }`
+ )
}
if (hasReservationExpired(reservation)) {
logger.warn(
payload.transactionId
} started with expired reservation ${
requestPayload.reservationId
- } (expiry date: ${reservation.expiryDate.toISOString()}))`,
- );
+ } (expiry date: ${reservation.expiryDate.toISOString()}))`
+ )
}
await chargingStation.removeReservation(
reservation,
- ReservationTerminationReason.TRANSACTION_STARTED,
- );
+ ReservationTerminationReason.TRANSACTION_STARTED
+ )
}
- chargingStation.stationInfo?.beginEndMeterValues &&
+ chargingStation.stationInfo?.beginEndMeterValues === true &&
(await chargingStation.ocppRequestService.requestHandler<
- OCPP16MeterValuesRequest,
- OCPP16MeterValuesResponse
+ OCPP16MeterValuesRequest,
+ OCPP16MeterValuesResponse
>(chargingStation, OCPP16RequestCommand.METER_VALUES, {
connectorId,
transactionId: payload.transactionId,
- meterValue: [connectorStatus.transactionBeginMeterValue],
- } as OCPP16MeterValuesRequest));
+ meterValue: [connectorStatus.transactionBeginMeterValue]
+ } satisfies OCPP16MeterValuesRequest))
await OCPP16ServiceUtils.sendAndSetConnectorStatus(
chargingStation,
connectorId,
- OCPP16ChargePointStatus.Charging,
- );
+ OCPP16ChargePointStatus.Charging
+ )
logger.info(
`${chargingStation.logPrefix()} Transaction with id ${payload.transactionId} STARTED on ${
chargingStation.stationInfo.chargingStationId
- }#${connectorId} for idTag '${requestPayload.idTag}'`,
- );
- if (chargingStation.stationInfo.powerSharedByConnectors) {
- ++chargingStation.powerDivider;
+ }#${connectorId} for idTag '${requestPayload.idTag}'`
+ )
+ if (chargingStation.stationInfo.powerSharedByConnectors === true) {
+ ++chargingStation.powerDivider
}
const configuredMeterValueSampleInterval = getConfigurationKey(
chargingStation,
- OCPP16StandardParametersKey.MeterValueSampleInterval,
- );
+ OCPP16StandardParametersKey.MeterValueSampleInterval
+ )
chargingStation.startMeterValues(
connectorId,
configuredMeterValueSampleInterval !== undefined
? secondsToMilliseconds(convertToInt(configuredMeterValueSampleInterval.value))
- : Constants.DEFAULT_METER_VALUES_INTERVAL,
- );
+ : Constants.DEFAULT_METER_VALUES_INTERVAL
+ )
} else {
logger.warn(
`${chargingStation.logPrefix()} Starting transaction with id ${
OCPP16ServiceUtils.hasReservation(chargingStation, connectorId, requestPayload.idTag)
? `, reservationId '${requestPayload.reservationId}'`
: ''
- }`,
- );
- await this.resetConnectorOnStartTransactionError(chargingStation, connectorId);
+ }`
+ )
+ await this.resetConnectorOnStartTransactionError(chargingStation, connectorId)
}
}
- private async resetConnectorOnStartTransactionError(
+ private async resetConnectorOnStartTransactionError (
chargingStation: ChargingStation,
- connectorId: number,
+ connectorId: number
): Promise<void> {
- const connectorStatus = chargingStation.getConnectorStatus(connectorId);
- resetConnectorStatus(connectorStatus!);
- chargingStation.stopMeterValues(connectorId);
+ const connectorStatus = chargingStation.getConnectorStatus(connectorId)
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ resetConnectorStatus(connectorStatus!)
+ chargingStation.stopMeterValues(connectorId)
if (connectorStatus?.status !== OCPP16ChargePointStatus.Available) {
await OCPP16ServiceUtils.sendAndSetConnectorStatus(
chargingStation,
connectorId,
- OCPP16ChargePointStatus.Available,
- );
+ OCPP16ChargePointStatus.Available
+ )
}
}
- private async handleResponseStopTransaction(
+ private async handleResponseStopTransaction (
chargingStation: ChargingStation,
payload: OCPP16StopTransactionResponse,
- requestPayload: OCPP16StopTransactionRequest,
+ requestPayload: OCPP16StopTransactionRequest
): Promise<void> {
const transactionConnectorId = chargingStation.getConnectorIdByTransactionId(
- requestPayload.transactionId,
- );
+ requestPayload.transactionId
+ )
if (isNullOrUndefined(transactionConnectorId)) {
logger.error(
`${chargingStation.logPrefix()} Trying to stop a non existing transaction with id ${
requestPayload.transactionId
- }`,
- );
- return;
+ }`
+ )
+ return
}
chargingStation.stationInfo?.beginEndMeterValues === true &&
chargingStation.stationInfo?.ocppStrictCompliance === false &&
chargingStation.stationInfo?.outOfOrderEndMeterValues === true &&
(await chargingStation.ocppRequestService.requestHandler<
- OCPP16MeterValuesRequest,
- OCPP16MeterValuesResponse
+ OCPP16MeterValuesRequest,
+ OCPP16MeterValuesResponse
>(chargingStation, OCPP16RequestCommand.METER_VALUES, {
connectorId: transactionConnectorId,
transactionId: requestPayload.transactionId,
meterValue: [
OCPP16ServiceUtils.buildTransactionEndMeterValue(
chargingStation,
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
transactionConnectorId!,
- requestPayload.meterStop,
- ),
- ],
- }));
+ requestPayload.meterStop
+ )
+ ]
+ }))
if (
- chargingStation.isChargingStationAvailable() === false ||
- chargingStation.isConnectorAvailable(transactionConnectorId!) === false
+ !chargingStation.isChargingStationAvailable() ||
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ !chargingStation.isConnectorAvailable(transactionConnectorId!)
) {
await OCPP16ServiceUtils.sendAndSetConnectorStatus(
chargingStation,
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
transactionConnectorId!,
- OCPP16ChargePointStatus.Unavailable,
- );
+ OCPP16ChargePointStatus.Unavailable
+ )
} else {
await OCPP16ServiceUtils.sendAndSetConnectorStatus(
chargingStation,
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
transactionConnectorId!,
- OCPP16ChargePointStatus.Available,
- );
+ OCPP16ChargePointStatus.Available
+ )
}
- if (chargingStation.stationInfo.powerSharedByConnectors) {
- chargingStation.powerDivider--;
+ if (chargingStation.stationInfo.powerSharedByConnectors === true) {
+ chargingStation.powerDivider--
}
- resetConnectorStatus(chargingStation.getConnectorStatus(transactionConnectorId!)!);
- chargingStation.stopMeterValues(transactionConnectorId!);
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ resetConnectorStatus(chargingStation.getConnectorStatus(transactionConnectorId!)!)
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ chargingStation.stopMeterValues(transactionConnectorId!)
const logMsg = `${chargingStation.logPrefix()} Transaction with id ${
requestPayload.transactionId
} STOPPED on ${
chargingStation.stationInfo.chargingStationId
- }#${transactionConnectorId} with status '${payload.idTagInfo?.status}'`;
+ }#${transactionConnectorId} with status '${payload.idTagInfo?.status}'`
if (
isNullOrUndefined(payload.idTagInfo) ||
payload.idTagInfo?.status === OCPP16AuthorizationStatus.ACCEPTED
) {
- logger.info(logMsg);
+ logger.info(logMsg)
} else {
- logger.warn(logMsg);
+ logger.warn(logMsg)
}
}
}
// Partial Copyright Jerome Benoit. 2021-2023. All Rights Reserved.
-import type { JSONSchemaType } from 'ajv';
+import type { JSONSchemaType } from 'ajv'
import {
type Interval,
addSeconds,
differenceInSeconds,
isAfter,
isBefore,
- isWithinInterval,
-} from 'date-fns';
+ isWithinInterval
+} from 'date-fns'
-import { OCPP16Constants } from './OCPP16Constants.js';
+import { OCPP16Constants } from './OCPP16Constants.js'
import {
type ChargingStation,
hasFeatureProfile,
- hasReservationExpired,
-} from '../../../charging-station/index.js';
+ hasReservationExpired
+} from '../../../charging-station/index.js'
import {
type GenericResponse,
type JsonType,
OCPP16AuthorizationStatus,
- OCPP16AvailabilityType,
+ type OCPP16AvailabilityType,
type OCPP16ChangeAvailabilityResponse,
OCPP16ChargePointStatus,
type OCPP16ChargingProfile,
type OCPP16MeterValue,
OCPP16MeterValueContext,
OCPP16MeterValueUnit,
- OCPP16RequestCommand,
+ type OCPP16RequestCommand,
OCPP16StandardParametersKey,
OCPP16StopTransactionReason,
type OCPP16SupportedFeatureProfiles,
- OCPPVersion,
-} from '../../../types/index.js';
-import { isNotEmptyArray, isNullOrUndefined, logger, roundTo } from '../../../utils/index.js';
-import { OCPPServiceUtils } from '../OCPPServiceUtils.js';
+ OCPPVersion
+} from '../../../types/index.js'
+import { isNotEmptyArray, isNullOrUndefined, logger, roundTo } from '../../../utils/index.js'
+import { OCPPServiceUtils } from '../OCPPServiceUtils.js'
export class OCPP16ServiceUtils extends OCPPServiceUtils {
- public static checkFeatureProfile(
+ public static checkFeatureProfile (
chargingStation: ChargingStation,
featureProfile: OCPP16SupportedFeatureProfiles,
- command: OCPP16RequestCommand | OCPP16IncomingRequestCommand,
+ command: OCPP16RequestCommand | OCPP16IncomingRequestCommand
): boolean {
- if (!hasFeatureProfile(chargingStation, featureProfile)) {
+ if (hasFeatureProfile(chargingStation, featureProfile) === false) {
logger.warn(
`${chargingStation.logPrefix()} Trying to '${command}' without '${featureProfile}' feature enabled in ${
OCPP16StandardParametersKey.SupportedFeatureProfiles
- } in configuration`,
- );
- return false;
+ } in configuration`
+ )
+ return false
}
- return true;
+ return true
}
- public static buildTransactionBeginMeterValue(
+ public static buildTransactionBeginMeterValue (
chargingStation: ChargingStation,
connectorId: number,
- meterStart: number,
+ meterStart: number
): OCPP16MeterValue {
const meterValue: OCPP16MeterValue = {
timestamp: new Date(),
- sampledValue: [],
- };
+ sampledValue: []
+ }
// Energy.Active.Import.Register measurand (default)
const sampledValueTemplate = OCPP16ServiceUtils.getSampledValueTemplate(
chargingStation,
- connectorId,
- );
+ connectorId
+ )
const unitDivider =
- sampledValueTemplate?.unit === OCPP16MeterValueUnit.KILO_WATT_HOUR ? 1000 : 1;
+ sampledValueTemplate?.unit === OCPP16MeterValueUnit.KILO_WATT_HOUR ? 1000 : 1
meterValue.sampledValue.push(
OCPP16ServiceUtils.buildSampledValue(
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
sampledValueTemplate!,
roundTo((meterStart ?? 0) / unitDivider, 4),
- OCPP16MeterValueContext.TRANSACTION_BEGIN,
- ),
- );
- return meterValue;
+ OCPP16MeterValueContext.TRANSACTION_BEGIN
+ )
+ )
+ return meterValue
}
- public static buildTransactionDataMeterValues(
+ public static buildTransactionDataMeterValues (
transactionBeginMeterValue: OCPP16MeterValue,
- transactionEndMeterValue: OCPP16MeterValue,
+ transactionEndMeterValue: OCPP16MeterValue
): OCPP16MeterValue[] {
- const meterValues: OCPP16MeterValue[] = [];
- meterValues.push(transactionBeginMeterValue);
- meterValues.push(transactionEndMeterValue);
- return meterValues;
+ const meterValues: OCPP16MeterValue[] = []
+ meterValues.push(transactionBeginMeterValue)
+ meterValues.push(transactionEndMeterValue)
+ return meterValues
}
public static remoteStopTransaction = async (
chargingStation: ChargingStation,
- connectorId: number,
+ connectorId: number
): Promise<GenericResponse> => {
await OCPP16ServiceUtils.sendAndSetConnectorStatus(
chargingStation,
connectorId,
- OCPP16ChargePointStatus.Finishing,
- );
+ OCPP16ChargePointStatus.Finishing
+ )
const stopResponse = await chargingStation.stopTransactionOnConnector(
connectorId,
- OCPP16StopTransactionReason.REMOTE,
- );
+ OCPP16StopTransactionReason.REMOTE
+ )
if (stopResponse.idTagInfo?.status === OCPP16AuthorizationStatus.ACCEPTED) {
- return OCPP16Constants.OCPP_RESPONSE_ACCEPTED;
+ return OCPP16Constants.OCPP_RESPONSE_ACCEPTED
}
- return OCPP16Constants.OCPP_RESPONSE_REJECTED;
- };
+ return OCPP16Constants.OCPP_RESPONSE_REJECTED
+ }
public static changeAvailability = async (
chargingStation: ChargingStation,
connectorIds: number[],
chargePointStatus: OCPP16ChargePointStatus,
- availabilityType: OCPP16AvailabilityType,
+ availabilityType: OCPP16AvailabilityType
): Promise<OCPP16ChangeAvailabilityResponse> => {
- const responses: OCPP16ChangeAvailabilityResponse[] = [];
+ const responses: OCPP16ChangeAvailabilityResponse[] = []
for (const connectorId of connectorIds) {
let response: OCPP16ChangeAvailabilityResponse =
- OCPP16Constants.OCPP_AVAILABILITY_RESPONSE_ACCEPTED;
- const connectorStatus = chargingStation.getConnectorStatus(connectorId)!;
+ OCPP16Constants.OCPP_AVAILABILITY_RESPONSE_ACCEPTED
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ const connectorStatus = chargingStation.getConnectorStatus(connectorId)!
if (connectorStatus?.transactionStarted === true) {
- response = OCPP16Constants.OCPP_AVAILABILITY_RESPONSE_SCHEDULED;
+ response = OCPP16Constants.OCPP_AVAILABILITY_RESPONSE_SCHEDULED
}
- connectorStatus.availability = availabilityType;
+ connectorStatus.availability = availabilityType
if (response === OCPP16Constants.OCPP_AVAILABILITY_RESPONSE_ACCEPTED) {
await OCPP16ServiceUtils.sendAndSetConnectorStatus(
chargingStation,
connectorId,
- chargePointStatus,
- );
+ chargePointStatus
+ )
}
- responses.push(response);
+ responses.push(response)
}
if (responses.includes(OCPP16Constants.OCPP_AVAILABILITY_RESPONSE_SCHEDULED)) {
- return OCPP16Constants.OCPP_AVAILABILITY_RESPONSE_SCHEDULED;
+ return OCPP16Constants.OCPP_AVAILABILITY_RESPONSE_SCHEDULED
}
- return OCPP16Constants.OCPP_AVAILABILITY_RESPONSE_ACCEPTED;
- };
+ return OCPP16Constants.OCPP_AVAILABILITY_RESPONSE_ACCEPTED
+ }
- public static setChargingProfile(
+ public static setChargingProfile (
chargingStation: ChargingStation,
connectorId: number,
- cp: OCPP16ChargingProfile,
+ cp: OCPP16ChargingProfile
): void {
if (isNullOrUndefined(chargingStation.getConnectorStatus(connectorId)?.chargingProfiles)) {
logger.error(
- `${chargingStation.logPrefix()} Trying to set a charging profile on connector id ${connectorId} with an uninitialized charging profiles array attribute, applying deferred initialization`,
- );
- chargingStation.getConnectorStatus(connectorId)!.chargingProfiles = [];
+ `${chargingStation.logPrefix()} Trying to set a charging profile on connector id ${connectorId} with an uninitialized charging profiles array attribute, applying deferred initialization`
+ )
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ chargingStation.getConnectorStatus(connectorId)!.chargingProfiles = []
}
- if (
- Array.isArray(chargingStation.getConnectorStatus(connectorId)?.chargingProfiles) === false
- ) {
+ if (!Array.isArray(chargingStation.getConnectorStatus(connectorId)?.chargingProfiles)) {
logger.error(
- `${chargingStation.logPrefix()} Trying to set a charging profile on connector id ${connectorId} with an improper attribute type for the charging profiles array, applying proper type deferred initialization`,
- );
- chargingStation.getConnectorStatus(connectorId)!.chargingProfiles = [];
+ `${chargingStation.logPrefix()} Trying to set a charging profile on connector id ${connectorId} with an improper attribute type for the charging profiles array, applying proper type deferred initialization`
+ )
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ chargingStation.getConnectorStatus(connectorId)!.chargingProfiles = []
}
- let cpReplaced = false;
+ let cpReplaced = false
if (isNotEmptyArray(chargingStation.getConnectorStatus(connectorId)?.chargingProfiles)) {
chargingStation
.getConnectorStatus(connectorId)
(chargingProfile.stackLevel === cp.stackLevel &&
chargingProfile.chargingProfilePurpose === cp.chargingProfilePurpose)
) {
- chargingStation.getConnectorStatus(connectorId)!.chargingProfiles![index] = cp;
- cpReplaced = true;
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ chargingStation.getConnectorStatus(connectorId)!.chargingProfiles![index] = cp
+ cpReplaced = true
}
- });
+ })
}
- !cpReplaced && chargingStation.getConnectorStatus(connectorId)?.chargingProfiles?.push(cp);
+ !cpReplaced && chargingStation.getConnectorStatus(connectorId)?.chargingProfiles?.push(cp)
}
public static clearChargingProfiles = (
chargingStation: ChargingStation,
commandPayload: OCPP16ClearChargingProfileRequest,
- chargingProfiles: OCPP16ChargingProfile[] | undefined,
+ chargingProfiles: OCPP16ChargingProfile[] | undefined
): boolean => {
- const { id, chargingProfilePurpose, stackLevel } = commandPayload;
- let clearedCP = false;
+ const { id, chargingProfilePurpose, stackLevel } = commandPayload
+ let clearedCP = false
if (isNotEmptyArray(chargingProfiles)) {
chargingProfiles?.forEach((chargingProfile: OCPP16ChargingProfile, index: number) => {
- let clearCurrentCP = false;
+ let clearCurrentCP = false
if (chargingProfile.chargingProfileId === id) {
- clearCurrentCP = true;
+ clearCurrentCP = true
}
- if (!chargingProfilePurpose && chargingProfile.stackLevel === stackLevel) {
- clearCurrentCP = true;
+ if (chargingProfilePurpose == null && chargingProfile.stackLevel === stackLevel) {
+ clearCurrentCP = true
}
- if (!stackLevel && chargingProfile.chargingProfilePurpose === chargingProfilePurpose) {
- clearCurrentCP = true;
+ if (
+ stackLevel == null &&
+ chargingProfile.chargingProfilePurpose === chargingProfilePurpose
+ ) {
+ clearCurrentCP = true
}
if (
chargingProfile.stackLevel === stackLevel &&
chargingProfile.chargingProfilePurpose === chargingProfilePurpose
) {
- clearCurrentCP = true;
+ clearCurrentCP = true
}
if (clearCurrentCP) {
- chargingProfiles.splice(index, 1);
+ chargingProfiles.splice(index, 1)
logger.debug(
`${chargingStation.logPrefix()} Matching charging profile(s) cleared: %j`,
- chargingProfile,
- );
- clearedCP = true;
+ chargingProfile
+ )
+ clearedCP = true
}
- });
+ })
}
- return clearedCP;
- };
+ return clearedCP
+ }
public static composeChargingSchedules = (
chargingScheduleHigher: OCPP16ChargingSchedule | undefined,
chargingScheduleLower: OCPP16ChargingSchedule | undefined,
- compositeInterval: Interval,
+ compositeInterval: Interval
): OCPP16ChargingSchedule | undefined => {
- if (!chargingScheduleHigher && !chargingScheduleLower) {
- return undefined;
+ if (chargingScheduleHigher == null && chargingScheduleLower == null) {
+ return undefined
}
- if (chargingScheduleHigher && !chargingScheduleLower) {
- return OCPP16ServiceUtils.composeChargingSchedule(chargingScheduleHigher, compositeInterval);
+ if (chargingScheduleHigher != null && chargingScheduleLower == null) {
+ return OCPP16ServiceUtils.composeChargingSchedule(chargingScheduleHigher, compositeInterval)
}
- if (!chargingScheduleHigher && chargingScheduleLower) {
- return OCPP16ServiceUtils.composeChargingSchedule(chargingScheduleLower, compositeInterval);
+ if (chargingScheduleHigher == null && chargingScheduleLower != null) {
+ return OCPP16ServiceUtils.composeChargingSchedule(chargingScheduleLower, compositeInterval)
}
const compositeChargingScheduleHigher: OCPP16ChargingSchedule | undefined =
- OCPP16ServiceUtils.composeChargingSchedule(chargingScheduleHigher!, compositeInterval);
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ OCPP16ServiceUtils.composeChargingSchedule(chargingScheduleHigher!, compositeInterval)
const compositeChargingScheduleLower: OCPP16ChargingSchedule | undefined =
- OCPP16ServiceUtils.composeChargingSchedule(chargingScheduleLower!, compositeInterval);
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ OCPP16ServiceUtils.composeChargingSchedule(chargingScheduleLower!, compositeInterval)
const compositeChargingScheduleHigherInterval: Interval = {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
start: compositeChargingScheduleHigher!.startSchedule!,
end: addSeconds(
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
compositeChargingScheduleHigher!.startSchedule!,
- compositeChargingScheduleHigher!.duration!,
- ),
- };
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ compositeChargingScheduleHigher!.duration!
+ )
+ }
const compositeChargingScheduleLowerInterval: Interval = {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
start: compositeChargingScheduleLower!.startSchedule!,
end: addSeconds(
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
compositeChargingScheduleLower!.startSchedule!,
- compositeChargingScheduleLower!.duration!,
- ),
- };
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ compositeChargingScheduleLower!.duration!
+ )
+ }
const higherFirst = isBefore(
compositeChargingScheduleHigherInterval.start,
- compositeChargingScheduleLowerInterval.start,
- );
+ compositeChargingScheduleLowerInterval.start
+ )
if (
!areIntervalsOverlapping(
compositeChargingScheduleHigherInterval,
- compositeChargingScheduleLowerInterval,
+ compositeChargingScheduleLowerInterval
)
) {
return {
...compositeChargingScheduleLower,
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
...compositeChargingScheduleHigher!,
startSchedule: higherFirst
? (compositeChargingScheduleHigherInterval.start as Date)
: (compositeChargingScheduleLowerInterval.start as Date),
duration: higherFirst
? differenceInSeconds(
- compositeChargingScheduleLowerInterval.end,
- compositeChargingScheduleHigherInterval.start,
- )
+ compositeChargingScheduleLowerInterval.end,
+ compositeChargingScheduleHigherInterval.start
+ )
: differenceInSeconds(
- compositeChargingScheduleHigherInterval.end,
- compositeChargingScheduleLowerInterval.start,
- ),
+ compositeChargingScheduleHigherInterval.end,
+ compositeChargingScheduleLowerInterval.start
+ ),
chargingSchedulePeriod: [
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
...compositeChargingScheduleHigher!.chargingSchedulePeriod.map((schedulePeriod) => {
return {
...schedulePeriod,
: schedulePeriod.startPeriod +
differenceInSeconds(
compositeChargingScheduleHigherInterval.start,
- compositeChargingScheduleLowerInterval.start,
- ),
- };
+ compositeChargingScheduleLowerInterval.start
+ )
+ }
}),
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
...compositeChargingScheduleLower!.chargingSchedulePeriod.map((schedulePeriod) => {
return {
...schedulePeriod,
? schedulePeriod.startPeriod +
differenceInSeconds(
compositeChargingScheduleLowerInterval.start,
- compositeChargingScheduleHigherInterval.start,
+ compositeChargingScheduleHigherInterval.start
)
- : 0,
- };
- }),
- ].sort((a, b) => a.startPeriod - b.startPeriod),
- };
+ : 0
+ }
+ })
+ ].sort((a, b) => a.startPeriod - b.startPeriod)
+ }
}
return {
...compositeChargingScheduleLower,
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
...compositeChargingScheduleHigher!,
startSchedule: higherFirst
? (compositeChargingScheduleHigherInterval.start as Date)
: (compositeChargingScheduleLowerInterval.start as Date),
duration: higherFirst
? differenceInSeconds(
- compositeChargingScheduleLowerInterval.end,
- compositeChargingScheduleHigherInterval.start,
- )
+ compositeChargingScheduleLowerInterval.end,
+ compositeChargingScheduleHigherInterval.start
+ )
: differenceInSeconds(
- compositeChargingScheduleHigherInterval.end,
- compositeChargingScheduleLowerInterval.start,
- ),
+ compositeChargingScheduleHigherInterval.end,
+ compositeChargingScheduleLowerInterval.start
+ ),
chargingSchedulePeriod: [
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
...compositeChargingScheduleHigher!.chargingSchedulePeriod.map((schedulePeriod) => {
return {
...schedulePeriod,
: schedulePeriod.startPeriod +
differenceInSeconds(
compositeChargingScheduleHigherInterval.start,
- compositeChargingScheduleLowerInterval.start,
- ),
- };
+ compositeChargingScheduleLowerInterval.start
+ )
+ }
}),
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
...compositeChargingScheduleLower!.chargingSchedulePeriod
.filter((schedulePeriod, index) => {
if (
isWithinInterval(
addSeconds(
compositeChargingScheduleLowerInterval.start,
- schedulePeriod.startPeriod,
+ schedulePeriod.startPeriod
),
{
start: compositeChargingScheduleLowerInterval.start,
- end: compositeChargingScheduleHigherInterval.end,
- },
+ end: compositeChargingScheduleHigherInterval.end
+ }
)
) {
- return false;
+ return false
}
if (
higherFirst &&
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
index < compositeChargingScheduleLower!.chargingSchedulePeriod.length - 1 &&
!isWithinInterval(
addSeconds(
compositeChargingScheduleLowerInterval.start,
- schedulePeriod.startPeriod,
+ schedulePeriod.startPeriod
),
{
start: compositeChargingScheduleLowerInterval.start,
- end: compositeChargingScheduleHigherInterval.end,
- },
+ end: compositeChargingScheduleHigherInterval.end
+ }
) &&
isWithinInterval(
addSeconds(
compositeChargingScheduleLowerInterval.start,
- compositeChargingScheduleLower!.chargingSchedulePeriod[index + 1].startPeriod,
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ compositeChargingScheduleLower!.chargingSchedulePeriod[index + 1].startPeriod
),
{
start: compositeChargingScheduleLowerInterval.start,
- end: compositeChargingScheduleHigherInterval.end,
- },
+ end: compositeChargingScheduleHigherInterval.end
+ }
)
) {
- return false;
+ return false
}
if (
!higherFirst &&
isWithinInterval(
addSeconds(
compositeChargingScheduleLowerInterval.start,
- schedulePeriod.startPeriod,
+ schedulePeriod.startPeriod
),
{
start: compositeChargingScheduleHigherInterval.start,
- end: compositeChargingScheduleLowerInterval.end,
- },
+ end: compositeChargingScheduleLowerInterval.end
+ }
)
) {
- return false;
+ return false
}
- return true;
+ return true
})
.map((schedulePeriod, index) => {
if (index === 0 && schedulePeriod.startPeriod !== 0) {
- schedulePeriod.startPeriod = 0;
+ schedulePeriod.startPeriod = 0
}
return {
...schedulePeriod,
? schedulePeriod.startPeriod +
differenceInSeconds(
compositeChargingScheduleLowerInterval.start,
- compositeChargingScheduleHigherInterval.start,
+ compositeChargingScheduleHigherInterval.start
)
- : 0,
- };
- }),
- ].sort((a, b) => a.startPeriod - b.startPeriod),
- };
- };
+ : 0
+ }
+ })
+ ].sort((a, b) => a.startPeriod - b.startPeriod)
+ }
+ }
public static hasReservation = (
chargingStation: ChargingStation,
connectorId: number,
- idTag: string,
+ idTag: string
): boolean => {
- const connectorReservation = chargingStation.getReservationBy('connectorId', connectorId);
- const chargingStationReservation = chargingStation.getReservationBy('connectorId', 0);
+ const connectorReservation = chargingStation.getReservationBy('connectorId', connectorId)
+ const chargingStationReservation = chargingStation.getReservationBy('connectorId', 0)
if (
(chargingStation.getConnectorStatus(connectorId)?.status ===
OCPP16ChargePointStatus.Reserved &&
- connectorReservation &&
+ connectorReservation != null &&
!hasReservationExpired(connectorReservation) &&
- // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
connectorReservation?.idTag === idTag) ||
(chargingStation.getConnectorStatus(0)?.status === OCPP16ChargePointStatus.Reserved &&
- chargingStationReservation &&
+ chargingStationReservation != null &&
!hasReservationExpired(chargingStationReservation) &&
chargingStationReservation?.idTag === idTag)
) {
logger.debug(
`${chargingStation.logPrefix()} Connector id ${connectorId} has a valid reservation for idTag ${idTag}: %j`,
- connectorReservation ?? chargingStationReservation,
- );
- return true;
+ connectorReservation ?? chargingStationReservation
+ )
+ return true
}
- return false;
- };
+ return false
+ }
public static parseJsonSchemaFile<T extends JsonType>(
relativePath: string,
moduleName?: string,
- methodName?: string,
+ methodName?: string
): JSONSchemaType<T> {
return super.parseJsonSchemaFile<T>(
relativePath,
OCPPVersion.VERSION_16,
moduleName,
- methodName,
- );
+ methodName
+ )
}
- private static composeChargingSchedule = (
+ private static readonly composeChargingSchedule = (
chargingSchedule: OCPP16ChargingSchedule,
- compositeInterval: Interval,
+ compositeInterval: Interval
): OCPP16ChargingSchedule | undefined => {
const chargingScheduleInterval: Interval = {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
start: chargingSchedule.startSchedule!,
- end: addSeconds(chargingSchedule.startSchedule!, chargingSchedule.duration!),
- };
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ end: addSeconds(chargingSchedule.startSchedule!, chargingSchedule.duration!)
+ }
if (areIntervalsOverlapping(chargingScheduleInterval, compositeInterval)) {
- chargingSchedule.chargingSchedulePeriod.sort((a, b) => a.startPeriod - b.startPeriod);
+ chargingSchedule.chargingSchedulePeriod.sort((a, b) => a.startPeriod - b.startPeriod)
if (isBefore(chargingScheduleInterval.start, compositeInterval.start)) {
return {
...chargingSchedule,
startSchedule: compositeInterval.start as Date,
duration: differenceInSeconds(
chargingScheduleInterval.end,
- compositeInterval.start as Date,
+ compositeInterval.start as Date
),
chargingSchedulePeriod: chargingSchedule.chargingSchedulePeriod
.filter((schedulePeriod, index) => {
if (
isWithinInterval(
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
addSeconds(chargingScheduleInterval.start, schedulePeriod.startPeriod)!,
- compositeInterval,
+ compositeInterval
)
) {
- return true;
+ return true
}
if (
index < chargingSchedule.chargingSchedulePeriod.length - 1 &&
!isWithinInterval(
addSeconds(chargingScheduleInterval.start, schedulePeriod.startPeriod),
- compositeInterval,
+ compositeInterval
) &&
isWithinInterval(
addSeconds(
chargingScheduleInterval.start,
- chargingSchedule.chargingSchedulePeriod[index + 1].startPeriod,
+ chargingSchedule.chargingSchedulePeriod[index + 1].startPeriod
),
- compositeInterval,
+ compositeInterval
)
) {
- return true;
+ return true
}
- return false;
+ return false
})
.map((schedulePeriod, index) => {
if (index === 0 && schedulePeriod.startPeriod !== 0) {
- schedulePeriod.startPeriod = 0;
+ schedulePeriod.startPeriod = 0
}
- return schedulePeriod;
- }),
- };
+ return schedulePeriod
+ })
+ }
}
if (isAfter(chargingScheduleInterval.end, compositeInterval.end)) {
return {
...chargingSchedule,
duration: differenceInSeconds(
compositeInterval.end as Date,
- chargingScheduleInterval.start,
+ chargingScheduleInterval.start
),
chargingSchedulePeriod: chargingSchedule.chargingSchedulePeriod.filter((schedulePeriod) =>
isWithinInterval(
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
addSeconds(chargingScheduleInterval.start, schedulePeriod.startPeriod)!,
- compositeInterval,
- ),
- ),
- };
+ compositeInterval
+ )
+ )
+ }
}
- return chargingSchedule;
+ return chargingSchedule
}
- };
+ }
}
import {
type ConnectorStatusTransition,
- OCPP20ConnectorStatusEnumType,
-} from '../../../types/index.js';
-import { OCPPConstants } from '../OCPPConstants.js';
+ OCPP20ConnectorStatusEnumType
+} from '../../../types/index.js'
+import { OCPPConstants } from '../OCPPConstants.js'
export class OCPP20Constants extends OCPPConstants {
static readonly ChargingStationStatusTransitions: Readonly<ConnectorStatusTransition[]> =
// { from: OCPP20ConnectorStatusEnumType.Available, to: OCPP20ConnectorStatusEnumType.Available },
{
from: OCPP20ConnectorStatusEnumType.Available,
- to: OCPP20ConnectorStatusEnumType.Unavailable,
+ to: OCPP20ConnectorStatusEnumType.Unavailable
},
{ from: OCPP20ConnectorStatusEnumType.Available, to: OCPP20ConnectorStatusEnumType.Faulted },
{ to: OCPP20ConnectorStatusEnumType.Unavailable },
{
from: OCPP20ConnectorStatusEnumType.Unavailable,
- to: OCPP20ConnectorStatusEnumType.Available,
+ to: OCPP20ConnectorStatusEnumType.Available
},
// {
// from: OCPP20ConnectorStatusEnumType.Unavailable,
// },
{
from: OCPP20ConnectorStatusEnumType.Unavailable,
- to: OCPP20ConnectorStatusEnumType.Faulted,
+ to: OCPP20ConnectorStatusEnumType.Faulted
},
{ to: OCPP20ConnectorStatusEnumType.Faulted },
{ from: OCPP20ConnectorStatusEnumType.Faulted, to: OCPP20ConnectorStatusEnumType.Available },
{
from: OCPP20ConnectorStatusEnumType.Faulted,
- to: OCPP20ConnectorStatusEnumType.Unavailable,
- },
+ to: OCPP20ConnectorStatusEnumType.Unavailable
+ }
// { from: OCPP20ConnectorStatusEnumType.Faulted, to: OCPP20ConnectorStatusEnumType.Faulted },
- ]);
+ ])
static readonly ConnectorStatusTransitions: Readonly<ConnectorStatusTransition[]> = Object.freeze(
[
{ from: OCPP20ConnectorStatusEnumType.Available, to: OCPP20ConnectorStatusEnumType.Reserved },
{
from: OCPP20ConnectorStatusEnumType.Available,
- to: OCPP20ConnectorStatusEnumType.Unavailable,
+ to: OCPP20ConnectorStatusEnumType.Unavailable
},
{ from: OCPP20ConnectorStatusEnumType.Available, to: OCPP20ConnectorStatusEnumType.Faulted },
// { to: OCPP20ConnectorStatusEnumType.Occupied },
// { from: OCPP20ConnectorStatusEnumType.Occupied, to: OCPP20ConnectorStatusEnumType.Reserved },
{
from: OCPP20ConnectorStatusEnumType.Occupied,
- to: OCPP20ConnectorStatusEnumType.Unavailable,
+ to: OCPP20ConnectorStatusEnumType.Unavailable
},
{ from: OCPP20ConnectorStatusEnumType.Occupied, to: OCPP20ConnectorStatusEnumType.Faulted },
// { to: OCPP20ConnectorStatusEnumType.Reserved },
// { from: OCPP20ConnectorStatusEnumType.Reserved, to: OCPP20ConnectorStatusEnumType.Reserved },
{
from: OCPP20ConnectorStatusEnumType.Reserved,
- to: OCPP20ConnectorStatusEnumType.Unavailable,
+ to: OCPP20ConnectorStatusEnumType.Unavailable
},
{ from: OCPP20ConnectorStatusEnumType.Reserved, to: OCPP20ConnectorStatusEnumType.Faulted },
{ to: OCPP20ConnectorStatusEnumType.Unavailable },
{
from: OCPP20ConnectorStatusEnumType.Unavailable,
- to: OCPP20ConnectorStatusEnumType.Available,
+ to: OCPP20ConnectorStatusEnumType.Available
},
{
from: OCPP20ConnectorStatusEnumType.Unavailable,
- to: OCPP20ConnectorStatusEnumType.Occupied,
+ to: OCPP20ConnectorStatusEnumType.Occupied
},
// { from: OCPP20ConnectorStatusEnumType.Unavailable, to: OCPP20ConnectorStatusEnumType.Reserved },
// { from: OCPP20ConnectorStatusEnumType.Unavailable, to: OCPP20ConnectorStatusEnumType.Unavailable },
{
from: OCPP20ConnectorStatusEnumType.Unavailable,
- to: OCPP20ConnectorStatusEnumType.Faulted,
+ to: OCPP20ConnectorStatusEnumType.Faulted
},
{ to: OCPP20ConnectorStatusEnumType.Faulted },
{ from: OCPP20ConnectorStatusEnumType.Faulted, to: OCPP20ConnectorStatusEnumType.Available },
{ from: OCPP20ConnectorStatusEnumType.Faulted, to: OCPP20ConnectorStatusEnumType.Reserved },
{
from: OCPP20ConnectorStatusEnumType.Faulted,
- to: OCPP20ConnectorStatusEnumType.Unavailable,
- },
+ to: OCPP20ConnectorStatusEnumType.Unavailable
+ }
// { from: OCPP20ConnectorStatusEnumType.Faulted, to: OCPP20ConnectorStatusEnumType.Faulted },
- ],
- );
+ ]
+ )
}
// Partial Copyright Jerome Benoit. 2021-2023. All Rights Reserved.
-import type { JSONSchemaType } from 'ajv';
+import type { JSONSchemaType } from 'ajv'
-import { OCPP20ServiceUtils } from './OCPP20ServiceUtils.js';
-import type { ChargingStation } from '../../../charging-station/index.js';
-import { OCPPError } from '../../../exception/index.js';
+import { OCPP20ServiceUtils } from './OCPP20ServiceUtils.js'
+import type { ChargingStation } from '../../../charging-station/index.js'
+import { OCPPError } from '../../../exception/index.js'
import {
ErrorType,
type IncomingRequestHandler,
type JsonType,
type OCPP20ClearCacheRequest,
OCPP20IncomingRequestCommand,
- OCPPVersion,
-} from '../../../types/index.js';
-import { logger } from '../../../utils/index.js';
-import { OCPPIncomingRequestService } from '../OCPPIncomingRequestService.js';
+ OCPPVersion
+} from '../../../types/index.js'
+import { logger } from '../../../utils/index.js'
+import { OCPPIncomingRequestService } from '../OCPPIncomingRequestService.js'
-const moduleName = 'OCPP20IncomingRequestService';
+const moduleName = 'OCPP20IncomingRequestService'
export class OCPP20IncomingRequestService extends OCPPIncomingRequestService {
- protected jsonSchemas: Map<OCPP20IncomingRequestCommand, JSONSchemaType<JsonType>>;
- private incomingRequestHandlers: Map<OCPP20IncomingRequestCommand, IncomingRequestHandler>;
+ protected jsonSchemas: Map<OCPP20IncomingRequestCommand, JSONSchemaType<JsonType>>
+ private readonly incomingRequestHandlers: Map<
+ OCPP20IncomingRequestCommand,
+ IncomingRequestHandler
+ >
- public constructor() {
+ public constructor () {
// if (new.target?.name === moduleName) {
- // throw new TypeError(`Cannot construct ${new.target?.name} instances directly`);
+ // throw new TypeError(`Cannot construct ${new.target?.name} instances directly`)
// }
- super(OCPPVersion.VERSION_20);
+ super(OCPPVersion.VERSION_20)
this.incomingRequestHandlers = new Map<OCPP20IncomingRequestCommand, IncomingRequestHandler>([
- [OCPP20IncomingRequestCommand.CLEAR_CACHE, this.handleRequestClearCache.bind(this)],
- ]);
+ [OCPP20IncomingRequestCommand.CLEAR_CACHE, this.handleRequestClearCache.bind(this)]
+ ])
this.jsonSchemas = new Map<OCPP20IncomingRequestCommand, JSONSchemaType<JsonType>>([
[
OCPP20IncomingRequestCommand.CLEAR_CACHE,
OCPP20ServiceUtils.parseJsonSchemaFile<OCPP20ClearCacheRequest>(
'assets/json-schemas/ocpp/2.0/ClearCacheRequest.json',
moduleName,
- 'constructor',
- ),
- ],
- ]);
+ 'constructor'
+ )
+ ]
+ ])
this.validatePayload = this.validatePayload.bind(this) as (
chargingStation: ChargingStation,
commandName: OCPP20IncomingRequestCommand,
- commandPayload: JsonType,
- ) => boolean;
+ commandPayload: JsonType
+ ) => boolean
}
public async incomingRequestHandler<ReqType extends JsonType, ResType extends JsonType>(
chargingStation: ChargingStation,
messageId: string,
commandName: OCPP20IncomingRequestCommand,
- commandPayload: ReqType,
+ commandPayload: ReqType
): Promise<void> {
- let response: ResType;
+ let response: ResType
if (
chargingStation.stationInfo?.ocppStrictCompliance === true &&
- chargingStation.inPendingState() === true &&
+ chargingStation.inPendingState() &&
(commandName === OCPP20IncomingRequestCommand.REQUEST_START_TRANSACTION ||
commandName === OCPP20IncomingRequestCommand.REQUEST_STOP_TRANSACTION)
) {
`${commandName} cannot be issued to handle request PDU ${JSON.stringify(
commandPayload,
undefined,
- 2,
+ 2
)} while the charging station is in pending state on the central server`,
commandName,
- commandPayload,
- );
+ commandPayload
+ )
}
if (
- chargingStation.isRegistered() === true ||
+ chargingStation.isRegistered() ||
(chargingStation.stationInfo?.ocppStrictCompliance === false &&
- chargingStation.inUnknownState() === true)
+ chargingStation.inUnknownState())
) {
if (
- this.incomingRequestHandlers.has(commandName) === true &&
- OCPP20ServiceUtils.isIncomingRequestCommandSupported(chargingStation, commandName) === true
+ this.incomingRequestHandlers.has(commandName) &&
+ OCPP20ServiceUtils.isIncomingRequestCommandSupported(chargingStation, commandName)
) {
try {
- this.validatePayload(chargingStation, commandName, commandPayload);
+ this.validatePayload(chargingStation, commandName, commandPayload)
// Call the method to build the response
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
response = (await this.incomingRequestHandlers.get(commandName)!(
chargingStation,
- commandPayload,
- )) as ResType;
+ commandPayload
+ )) as ResType
} catch (error) {
// Log
logger.error(
`${chargingStation.logPrefix()} ${moduleName}.incomingRequestHandler: Handle incoming request error:`,
- error,
- );
- throw error;
+ error
+ )
+ throw error
}
} else {
// Throw exception
`${commandName} is not implemented to handle request PDU ${JSON.stringify(
commandPayload,
undefined,
- 2,
+ 2
)}`,
commandName,
- commandPayload,
- );
+ commandPayload
+ )
}
} else {
throw new OCPPError(
`${commandName} cannot be issued to handle request PDU ${JSON.stringify(
commandPayload,
undefined,
- 2,
+ 2
)} while the charging station is not registered on the central server.`,
commandName,
- commandPayload,
- );
+ commandPayload
+ )
}
// Send the built response
await chargingStation.ocppRequestService.sendResponse(
chargingStation,
messageId,
response,
- commandName,
- );
+ commandName
+ )
}
- private validatePayload(
+ private validatePayload (
chargingStation: ChargingStation,
commandName: OCPP20IncomingRequestCommand,
- commandPayload: JsonType,
+ commandPayload: JsonType
): boolean {
- if (this.jsonSchemas.has(commandName) === true) {
+ if (this.jsonSchemas.has(commandName)) {
return this.validateIncomingRequestPayload(
chargingStation,
commandName,
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.jsonSchemas.get(commandName)!,
- commandPayload,
- );
+ commandPayload
+ )
}
logger.warn(
- `${chargingStation.logPrefix()} ${moduleName}.validatePayload: No JSON schema found for command '${commandName}' PDU validation`,
- );
- return false;
+ `${chargingStation.logPrefix()} ${moduleName}.validatePayload: No JSON schema found for command '${commandName}' PDU validation`
+ )
+ return false
}
}
// Partial Copyright Jerome Benoit. 2021-2023. All Rights Reserved.
-import type { JSONSchemaType } from 'ajv';
+import type { JSONSchemaType } from 'ajv'
-import { OCPP20Constants } from './OCPP20Constants.js';
-import { OCPP20ServiceUtils } from './OCPP20ServiceUtils.js';
-import type { ChargingStation } from '../../../charging-station/index.js';
-import { OCPPError } from '../../../exception/index.js';
+import { OCPP20Constants } from './OCPP20Constants.js'
+import { OCPP20ServiceUtils } from './OCPP20ServiceUtils.js'
+import type { ChargingStation } from '../../../charging-station/index.js'
+import { OCPPError } from '../../../exception/index.js'
import {
ErrorType,
type JsonObject,
OCPP20RequestCommand,
type OCPP20StatusNotificationRequest,
OCPPVersion,
- type RequestParams,
-} from '../../../types/index.js';
-import { generateUUID } from '../../../utils/index.js';
-import { OCPPRequestService } from '../OCPPRequestService.js';
-import type { OCPPResponseService } from '../OCPPResponseService.js';
+ type RequestParams
+} from '../../../types/index.js'
+import { generateUUID } from '../../../utils/index.js'
+import { OCPPRequestService } from '../OCPPRequestService.js'
+import type { OCPPResponseService } from '../OCPPResponseService.js'
-const moduleName = 'OCPP20RequestService';
+const moduleName = 'OCPP20RequestService'
export class OCPP20RequestService extends OCPPRequestService {
- protected jsonSchemas: Map<OCPP20RequestCommand, JSONSchemaType<JsonType>>;
+ protected jsonSchemas: Map<OCPP20RequestCommand, JSONSchemaType<JsonType>>
- public constructor(ocppResponseService: OCPPResponseService) {
+ public constructor (ocppResponseService: OCPPResponseService) {
// if (new.target?.name === moduleName) {
- // throw new TypeError(`Cannot construct ${new.target?.name} instances directly`);
+ // throw new TypeError(`Cannot construct ${new.target?.name} instances directly`)
// }
- super(OCPPVersion.VERSION_20, ocppResponseService);
+ super(OCPPVersion.VERSION_20, ocppResponseService)
this.jsonSchemas = new Map<OCPP20RequestCommand, JSONSchemaType<JsonType>>([
[
OCPP20RequestCommand.BOOT_NOTIFICATION,
OCPP20ServiceUtils.parseJsonSchemaFile<OCPP20BootNotificationRequest>(
'assets/json-schemas/ocpp/2.0/BootNotificationRequest.json',
moduleName,
- 'constructor',
- ),
+ 'constructor'
+ )
],
[
OCPP20RequestCommand.HEARTBEAT,
OCPP20ServiceUtils.parseJsonSchemaFile<OCPP20HeartbeatRequest>(
'assets/json-schemas/ocpp/2.0/HeartbeatRequest.json',
moduleName,
- 'constructor',
- ),
+ 'constructor'
+ )
],
[
OCPP20RequestCommand.STATUS_NOTIFICATION,
OCPP20ServiceUtils.parseJsonSchemaFile<OCPP20StatusNotificationRequest>(
'assets/json-schemas/ocpp/2.0/StatusNotificationRequest.json',
moduleName,
- 'constructor',
- ),
- ],
- ]);
+ 'constructor'
+ )
+ ]
+ ])
this.buildRequestPayload = this.buildRequestPayload.bind(this) as <Request extends JsonType>(
chargingStation: ChargingStation,
commandName: OCPP20RequestCommand,
- commandParams?: JsonType,
- ) => Request;
+ commandParams?: JsonType
+ ) => Request
}
public async requestHandler<RequestType extends JsonType, ResponseType extends JsonType>(
chargingStation: ChargingStation,
commandName: OCPP20RequestCommand,
commandParams?: JsonType,
- params?: RequestParams,
+ params?: RequestParams
): Promise<ResponseType> {
// FIXME?: add sanity checks on charging station availability, connector availability, connector status, etc.
- if (OCPP20ServiceUtils.isRequestCommandSupported(chargingStation, commandName) === true) {
+ if (OCPP20ServiceUtils.isRequestCommandSupported(chargingStation, commandName)) {
return (await this.sendMessage(
chargingStation,
generateUUID(),
this.buildRequestPayload<RequestType>(chargingStation, commandName, commandParams),
commandName,
- params,
- )) as ResponseType;
+ params
+ )) as ResponseType
}
// OCPPError usage here is debatable: it's an error in the OCPP stack but not targeted to sendError().
throw new OCPPError(
ErrorType.NOT_SUPPORTED,
`Unsupported OCPP command '${commandName}'`,
commandName,
- commandParams,
- );
+ commandParams
+ )
}
private buildRequestPayload<Request extends JsonType>(
chargingStation: ChargingStation,
commandName: OCPP20RequestCommand,
- commandParams?: JsonType,
+ commandParams?: JsonType
): Request {
- commandParams = commandParams as JsonObject;
+ commandParams = commandParams as JsonObject
switch (commandName) {
case OCPP20RequestCommand.BOOT_NOTIFICATION:
- return commandParams as unknown as Request;
+ return commandParams as unknown as Request
case OCPP20RequestCommand.HEARTBEAT:
- return OCPP20Constants.OCPP_RESPONSE_EMPTY as unknown as Request;
+ return OCPP20Constants.OCPP_RESPONSE_EMPTY as unknown as Request
case OCPP20RequestCommand.STATUS_NOTIFICATION:
return {
timestamp: new Date(),
- ...commandParams,
- } as unknown as Request;
+ ...commandParams
+ } as unknown as Request
default:
// OCPPError usage here is debatable: it's an error in the OCPP stack but not targeted to sendError().
throw new OCPPError(
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
`Unsupported OCPP command '${commandName}'`,
commandName,
- commandParams,
- );
+ commandParams
+ )
}
}
}
// Partial Copyright Jerome Benoit. 2021-2023. All Rights Reserved.
-import type { JSONSchemaType } from 'ajv';
+import type { JSONSchemaType } from 'ajv'
-import { OCPP20ServiceUtils } from './OCPP20ServiceUtils.js';
-import { type ChargingStation, addConfigurationKey } from '../../../charging-station/index.js';
-import { OCPPError } from '../../../exception/index.js';
+import { OCPP20ServiceUtils } from './OCPP20ServiceUtils.js'
+import { type ChargingStation, addConfigurationKey } from '../../../charging-station/index.js'
+import { OCPPError } from '../../../exception/index.js'
import {
ErrorType,
type JsonType,
type OCPP20StatusNotificationResponse,
OCPPVersion,
RegistrationStatusEnumType,
- type ResponseHandler,
-} from '../../../types/index.js';
-import { logger } from '../../../utils/index.js';
-import { OCPPResponseService } from '../OCPPResponseService.js';
+ type ResponseHandler
+} from '../../../types/index.js'
+import { logger } from '../../../utils/index.js'
+import { OCPPResponseService } from '../OCPPResponseService.js'
-const moduleName = 'OCPP20ResponseService';
+const moduleName = 'OCPP20ResponseService'
export class OCPP20ResponseService extends OCPPResponseService {
public jsonIncomingRequestResponseSchemas: Map<
- OCPP20IncomingRequestCommand,
- JSONSchemaType<JsonType>
- >;
+ OCPP20IncomingRequestCommand,
+ JSONSchemaType<JsonType>
+ >
- private responseHandlers: Map<OCPP20RequestCommand, ResponseHandler>;
- private jsonSchemas: Map<OCPP20RequestCommand, JSONSchemaType<JsonType>>;
+ private readonly responseHandlers: Map<OCPP20RequestCommand, ResponseHandler>
+ private readonly jsonSchemas: Map<OCPP20RequestCommand, JSONSchemaType<JsonType>>
- public constructor() {
+ public constructor () {
// if (new.target?.name === moduleName) {
- // throw new TypeError(`Cannot construct ${new.target?.name} instances directly`);
+ // throw new TypeError(`Cannot construct ${new.target?.name} instances directly`)
// }
- super(OCPPVersion.VERSION_20);
+ super(OCPPVersion.VERSION_20)
this.responseHandlers = new Map<OCPP20RequestCommand, ResponseHandler>([
[
OCPP20RequestCommand.BOOT_NOTIFICATION,
- this.handleResponseBootNotification.bind(this) as ResponseHandler,
+ this.handleResponseBootNotification.bind(this) as ResponseHandler
],
[OCPP20RequestCommand.HEARTBEAT, this.emptyResponseHandler.bind(this) as ResponseHandler],
[
OCPP20RequestCommand.STATUS_NOTIFICATION,
- this.emptyResponseHandler.bind(this) as ResponseHandler,
- ],
- ]);
+ this.emptyResponseHandler.bind(this) as ResponseHandler
+ ]
+ ])
this.jsonSchemas = new Map<OCPP20RequestCommand, JSONSchemaType<JsonType>>([
[
OCPP20RequestCommand.BOOT_NOTIFICATION,
OCPP20ServiceUtils.parseJsonSchemaFile<OCPP20BootNotificationResponse>(
'assets/json-schemas/ocpp/2.0/BootNotificationResponse.json',
moduleName,
- 'constructor',
- ),
+ 'constructor'
+ )
],
[
OCPP20RequestCommand.HEARTBEAT,
OCPP20ServiceUtils.parseJsonSchemaFile<OCPP20HeartbeatResponse>(
'assets/json-schemas/ocpp/2.0/HeartbeatResponse.json',
moduleName,
- 'constructor',
- ),
+ 'constructor'
+ )
],
[
OCPP20RequestCommand.STATUS_NOTIFICATION,
OCPP20ServiceUtils.parseJsonSchemaFile<OCPP20StatusNotificationResponse>(
'assets/json-schemas/ocpp/2.0/StatusNotificationResponse.json',
moduleName,
- 'constructor',
- ),
- ],
- ]);
+ 'constructor'
+ )
+ ]
+ ])
this.jsonIncomingRequestResponseSchemas = new Map([
[
OCPP20IncomingRequestCommand.CLEAR_CACHE,
OCPP20ServiceUtils.parseJsonSchemaFile<OCPP20ClearCacheResponse>(
'assets/json-schemas/ocpp/2.0/ClearCacheResponse.json',
moduleName,
- 'constructor',
- ),
- ],
- ]);
+ 'constructor'
+ )
+ ]
+ ])
this.validatePayload = this.validatePayload.bind(this) as (
chargingStation: ChargingStation,
commandName: OCPP20RequestCommand,
- payload: JsonType,
- ) => boolean;
+ payload: JsonType
+ ) => boolean
}
public async responseHandler<ReqType extends JsonType, ResType extends JsonType>(
chargingStation: ChargingStation,
commandName: OCPP20RequestCommand,
payload: ResType,
- requestPayload: ReqType,
+ requestPayload: ReqType
): Promise<void> {
- if (
- chargingStation.isRegistered() === true ||
- commandName === OCPP20RequestCommand.BOOT_NOTIFICATION
- ) {
+ if (chargingStation.isRegistered() || commandName === OCPP20RequestCommand.BOOT_NOTIFICATION) {
if (
- this.responseHandlers.has(commandName) === true &&
- OCPP20ServiceUtils.isRequestCommandSupported(chargingStation, commandName) === true
+ this.responseHandlers.has(commandName) &&
+ OCPP20ServiceUtils.isRequestCommandSupported(chargingStation, commandName)
) {
try {
- this.validatePayload(chargingStation, commandName, payload);
- await this.responseHandlers.get(commandName)!(chargingStation, payload, requestPayload);
+ this.validatePayload(chargingStation, commandName, payload)
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ await this.responseHandlers.get(commandName)!(chargingStation, payload, requestPayload)
} catch (error) {
logger.error(
`${chargingStation.logPrefix()} ${moduleName}.responseHandler: Handle response error:`,
- error,
- );
- throw error;
+ error
+ )
+ throw error
}
} else {
// Throw exception
`${commandName} is not implemented to handle response PDU ${JSON.stringify(
payload,
undefined,
- 2,
+ 2
)}`,
commandName,
- payload,
- );
+ payload
+ )
}
} else {
throw new OCPPError(
`${commandName} cannot be issued to handle response PDU ${JSON.stringify(
payload,
undefined,
- 2,
+ 2
)} while the charging station is not registered on the central server.`,
commandName,
- payload,
- );
+ payload
+ )
}
}
- private validatePayload(
+ private validatePayload (
chargingStation: ChargingStation,
commandName: OCPP20RequestCommand,
- payload: JsonType,
+ payload: JsonType
): boolean {
- if (this.jsonSchemas.has(commandName) === true) {
+ if (this.jsonSchemas.has(commandName)) {
return this.validateResponsePayload(
chargingStation,
commandName,
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.jsonSchemas.get(commandName)!,
- payload,
- );
+ payload
+ )
}
logger.warn(
- `${chargingStation.logPrefix()} ${moduleName}.validatePayload: No JSON schema found for command '${commandName}' PDU validation`,
- );
- return false;
+ `${chargingStation.logPrefix()} ${moduleName}.validatePayload: No JSON schema found for command '${commandName}' PDU validation`
+ )
+ return false
}
- private handleResponseBootNotification(
+ private handleResponseBootNotification (
chargingStation: ChargingStation,
- payload: OCPP20BootNotificationResponse,
+ payload: OCPP20BootNotificationResponse
): void {
if (payload.status === RegistrationStatusEnumType.ACCEPTED) {
addConfigurationKey(
OCPP20OptionalVariableName.HeartbeatInterval,
payload.interval.toString(),
{},
- { overwrite: true, save: true },
- );
- OCPP20ServiceUtils.startHeartbeatInterval(chargingStation, payload.interval);
+ { overwrite: true, save: true }
+ )
+ OCPP20ServiceUtils.startHeartbeatInterval(chargingStation, payload.interval)
}
if (Object.values(RegistrationStatusEnumType).includes(payload.status)) {
const logMsg = `${chargingStation.logPrefix()} Charging station in '${
payload.status
- }' state on the central server`;
+ }' state on the central server`
payload.status === RegistrationStatusEnumType.REJECTED
? logger.warn(logMsg)
- : logger.info(logMsg);
+ : logger.info(logMsg)
} else {
logger.error(
`${chargingStation.logPrefix()} Charging station boot notification response received: %j with undefined registration status`,
- payload,
- );
+ payload
+ )
}
}
}
// Partial Copyright Jerome Benoit. 2021-2023. All Rights Reserved.
-import type { JSONSchemaType } from 'ajv';
+import type { JSONSchemaType } from 'ajv'
-import { type JsonType, OCPPVersion } from '../../../types/index.js';
-import { OCPPServiceUtils } from '../OCPPServiceUtils.js';
+import { type JsonType, OCPPVersion } from '../../../types/index.js'
+import { OCPPServiceUtils } from '../OCPPServiceUtils.js'
export class OCPP20ServiceUtils extends OCPPServiceUtils {
public static parseJsonSchemaFile<T extends JsonType>(
relativePath: string,
moduleName?: string,
- methodName?: string,
+ methodName?: string
): JSONSchemaType<T> {
return super.parseJsonSchemaFile<T>(
relativePath,
OCPPVersion.VERSION_20,
moduleName,
- methodName,
- );
+ methodName
+ )
}
}
MeterValueMeasurand,
ReservationStatus,
TriggerMessageStatus,
- UnlockStatus,
-} from '../../types/index.js';
-import { Constants } from '../../utils/index.js';
+ UnlockStatus
+} from '../../types/index.js'
+import { Constants } from '../../utils/index.js'
+// eslint-disable-next-line @typescript-eslint/no-extraneous-class
export class OCPPConstants {
- static readonly OCPP_WEBSOCKET_TIMEOUT = 60000; // Ms
- static readonly OCPP_TRIGGER_MESSAGE_DELAY = 500; // Ms
+ static readonly OCPP_WEBSOCKET_TIMEOUT = 60000 // Ms
+ static readonly OCPP_TRIGGER_MESSAGE_DELAY = 500 // Ms
static readonly OCPP_MEASURANDS_SUPPORTED = Object.freeze([
MeterValueMeasurand.STATE_OF_CHARGE,
MeterValueMeasurand.VOLTAGE,
MeterValueMeasurand.POWER_ACTIVE_IMPORT,
MeterValueMeasurand.CURRENT_IMPORT,
- MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER,
- ]);
+ MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER
+ ])
- static readonly OCPP_REQUEST_EMPTY = Constants.EMPTY_FROZEN_OBJECT;
- static readonly OCPP_RESPONSE_EMPTY = Constants.EMPTY_FROZEN_OBJECT;
- static readonly OCPP_RESPONSE_ACCEPTED = Object.freeze({ status: GenericStatus.Accepted });
- static readonly OCPP_RESPONSE_REJECTED = Object.freeze({ status: GenericStatus.Rejected });
+ static readonly OCPP_REQUEST_EMPTY = Constants.EMPTY_FROZEN_OBJECT
+ static readonly OCPP_RESPONSE_EMPTY = Constants.EMPTY_FROZEN_OBJECT
+ static readonly OCPP_RESPONSE_ACCEPTED = Object.freeze({ status: GenericStatus.Accepted })
+ static readonly OCPP_RESPONSE_REJECTED = Object.freeze({ status: GenericStatus.Rejected })
static readonly OCPP_CONFIGURATION_RESPONSE_ACCEPTED = Object.freeze({
- status: ConfigurationStatus.ACCEPTED,
- });
+ status: ConfigurationStatus.ACCEPTED
+ })
static readonly OCPP_CONFIGURATION_RESPONSE_REJECTED = Object.freeze({
- status: ConfigurationStatus.REJECTED,
- });
+ status: ConfigurationStatus.REJECTED
+ })
static readonly OCPP_CONFIGURATION_RESPONSE_REBOOT_REQUIRED = Object.freeze({
- status: ConfigurationStatus.REBOOT_REQUIRED,
- });
+ status: ConfigurationStatus.REBOOT_REQUIRED
+ })
static readonly OCPP_CONFIGURATION_RESPONSE_NOT_SUPPORTED = Object.freeze({
- status: ConfigurationStatus.NOT_SUPPORTED,
- });
+ status: ConfigurationStatus.NOT_SUPPORTED
+ })
static readonly OCPP_SET_CHARGING_PROFILE_RESPONSE_ACCEPTED = Object.freeze({
- status: ChargingProfileStatus.ACCEPTED,
- });
+ status: ChargingProfileStatus.ACCEPTED
+ })
static readonly OCPP_SET_CHARGING_PROFILE_RESPONSE_REJECTED = Object.freeze({
- status: ChargingProfileStatus.REJECTED,
- });
+ status: ChargingProfileStatus.REJECTED
+ })
static readonly OCPP_SET_CHARGING_PROFILE_RESPONSE_NOT_SUPPORTED = Object.freeze({
- status: ChargingProfileStatus.NOT_SUPPORTED,
- });
+ status: ChargingProfileStatus.NOT_SUPPORTED
+ })
static readonly OCPP_CLEAR_CHARGING_PROFILE_RESPONSE_ACCEPTED = Object.freeze({
- status: ClearChargingProfileStatus.ACCEPTED,
- });
+ status: ClearChargingProfileStatus.ACCEPTED
+ })
static readonly OCPP_CLEAR_CHARGING_PROFILE_RESPONSE_UNKNOWN = Object.freeze({
- status: ClearChargingProfileStatus.UNKNOWN,
- });
+ status: ClearChargingProfileStatus.UNKNOWN
+ })
- static readonly OCPP_RESPONSE_UNLOCKED = Object.freeze({ status: UnlockStatus.UNLOCKED });
+ static readonly OCPP_RESPONSE_UNLOCKED = Object.freeze({ status: UnlockStatus.UNLOCKED })
static readonly OCPP_RESPONSE_UNLOCK_FAILED = Object.freeze({
- status: UnlockStatus.UNLOCK_FAILED,
- });
+ status: UnlockStatus.UNLOCK_FAILED
+ })
static readonly OCPP_RESPONSE_UNLOCK_NOT_SUPPORTED = Object.freeze({
- status: UnlockStatus.NOT_SUPPORTED,
- });
+ status: UnlockStatus.NOT_SUPPORTED
+ })
static readonly OCPP_AVAILABILITY_RESPONSE_ACCEPTED = Object.freeze({
- status: AvailabilityStatus.ACCEPTED,
- });
+ status: AvailabilityStatus.ACCEPTED
+ })
static readonly OCPP_AVAILABILITY_RESPONSE_REJECTED = Object.freeze({
- status: AvailabilityStatus.REJECTED,
- });
+ status: AvailabilityStatus.REJECTED
+ })
static readonly OCPP_AVAILABILITY_RESPONSE_SCHEDULED = Object.freeze({
- status: AvailabilityStatus.SCHEDULED,
- });
+ status: AvailabilityStatus.SCHEDULED
+ })
static readonly OCPP_TRIGGER_MESSAGE_RESPONSE_ACCEPTED = Object.freeze({
- status: TriggerMessageStatus.ACCEPTED,
- });
+ status: TriggerMessageStatus.ACCEPTED
+ })
static readonly OCPP_TRIGGER_MESSAGE_RESPONSE_REJECTED = Object.freeze({
- status: TriggerMessageStatus.REJECTED,
- });
+ status: TriggerMessageStatus.REJECTED
+ })
static readonly OCPP_TRIGGER_MESSAGE_RESPONSE_NOT_IMPLEMENTED = Object.freeze({
- status: TriggerMessageStatus.NOT_IMPLEMENTED,
- });
+ status: TriggerMessageStatus.NOT_IMPLEMENTED
+ })
static readonly OCPP_DATA_TRANSFER_RESPONSE_ACCEPTED = Object.freeze({
- status: DataTransferStatus.ACCEPTED,
- });
+ status: DataTransferStatus.ACCEPTED
+ })
static readonly OCPP_DATA_TRANSFER_RESPONSE_REJECTED = Object.freeze({
- status: DataTransferStatus.REJECTED,
- });
+ status: DataTransferStatus.REJECTED
+ })
static readonly OCPP_DATA_TRANSFER_RESPONSE_UNKNOWN_VENDOR_ID = Object.freeze({
- status: DataTransferStatus.UNKNOWN_VENDOR_ID,
- });
+ status: DataTransferStatus.UNKNOWN_VENDOR_ID
+ })
static readonly OCPP_RESERVATION_RESPONSE_ACCEPTED = Object.freeze({
- status: ReservationStatus.ACCEPTED,
- }); // Reservation has been made
+ status: ReservationStatus.ACCEPTED
+ }) // Reservation has been made
static readonly OCPP_RESERVATION_RESPONSE_FAULTED = Object.freeze({
- status: ReservationStatus.FAULTED,
- }); // Reservation has not been made, because of connector in FAULTED state
+ status: ReservationStatus.FAULTED
+ }) // Reservation has not been made, because of connector in FAULTED state
static readonly OCPP_RESERVATION_RESPONSE_OCCUPIED = Object.freeze({
- status: ReservationStatus.OCCUPIED,
- }); // Reservation has not been made, because all connectors are OCCUPIED
+ status: ReservationStatus.OCCUPIED
+ }) // Reservation has not been made, because all connectors are OCCUPIED
static readonly OCPP_RESERVATION_RESPONSE_REJECTED = Object.freeze({
- status: ReservationStatus.REJECTED,
- }); // Reservation has not been made, because charging station is not configured to accept reservations
+ status: ReservationStatus.REJECTED
+ }) // Reservation has not been made, because charging station is not configured to accept reservations
static readonly OCPP_RESERVATION_RESPONSE_UNAVAILABLE = Object.freeze({
- status: ReservationStatus.UNAVAILABLE,
- }); // Reservation has not been made, because connector is in UNAVAILABLE state
+ status: ReservationStatus.UNAVAILABLE
+ }) // Reservation has not been made, because connector is in UNAVAILABLE state
static readonly OCPP_CANCEL_RESERVATION_RESPONSE_ACCEPTED = Object.freeze({
- status: GenericStatus.Accepted,
- }); // Reservation for id has been cancelled
+ status: GenericStatus.Accepted
+ }) // Reservation for id has been cancelled
static readonly OCPP_CANCEL_RESERVATION_RESPONSE_REJECTED = Object.freeze({
- status: GenericStatus.Rejected,
- }); // Reservation could not be cancelled, because there is no reservation active for id
+ status: GenericStatus.Rejected
+ }) // Reservation could not be cancelled, because there is no reservation active for id
- protected constructor() {
+ protected constructor () {
// This is intentional
}
}
-import _Ajv, { type JSONSchemaType, type ValidateFunction } from 'ajv';
-import _ajvFormats from 'ajv-formats';
+import _Ajv, { type JSONSchemaType, type ValidateFunction } from 'ajv'
+import _ajvFormats from 'ajv-formats'
-import { OCPPConstants } from './OCPPConstants.js';
-import { OCPPServiceUtils } from './OCPPServiceUtils.js';
-import { type ChargingStation, getIdTagsFile } from '../../charging-station/index.js';
-import { OCPPError } from '../../exception/index.js';
+import { OCPPConstants } from './OCPPConstants.js'
+import { OCPPServiceUtils } from './OCPPServiceUtils.js'
+import { type ChargingStation, getIdTagsFile } from '../../charging-station/index.js'
+import { OCPPError } from '../../exception/index.js'
import type {
ClearCacheResponse,
HandleErrorParams,
IncomingRequestCommand,
JsonType,
- OCPPVersion,
-} from '../../types/index.js';
-import { logger, setDefaultErrorParams } from '../../utils/index.js';
-type Ajv = _Ajv.default;
-const Ajv = _Ajv.default;
-const ajvFormats = _ajvFormats.default;
+ OCPPVersion
+} from '../../types/index.js'
+import { logger, setDefaultErrorParams } from '../../utils/index.js'
+type Ajv = _Ajv.default
+// eslint-disable-next-line @typescript-eslint/no-redeclare
+const Ajv = _Ajv.default
+const ajvFormats = _ajvFormats.default
-const moduleName = 'OCPPIncomingRequestService';
+const moduleName = 'OCPPIncomingRequestService'
export abstract class OCPPIncomingRequestService {
- private static instance: OCPPIncomingRequestService | null = null;
- private readonly version: OCPPVersion;
- private readonly ajv: Ajv;
- private jsonValidateFunctions: Map<IncomingRequestCommand, ValidateFunction<JsonType>>;
- protected abstract jsonSchemas: Map<IncomingRequestCommand, JSONSchemaType<JsonType>>;
+ private static instance: OCPPIncomingRequestService | null = null
+ private readonly version: OCPPVersion
+ private readonly ajv: Ajv
+ private readonly jsonValidateFunctions: Map<IncomingRequestCommand, ValidateFunction<JsonType>>
+ protected abstract jsonSchemas: Map<IncomingRequestCommand, JSONSchemaType<JsonType>>
- protected constructor(version: OCPPVersion) {
- this.version = version;
+ protected constructor (version: OCPPVersion) {
+ this.version = version
this.ajv = new Ajv({
keywords: ['javaType'],
- multipleOfPrecision: 2,
- });
- ajvFormats(this.ajv);
- this.jsonValidateFunctions = new Map<IncomingRequestCommand, ValidateFunction<JsonType>>();
+ multipleOfPrecision: 2
+ })
+ ajvFormats(this.ajv)
+ this.jsonValidateFunctions = new Map<IncomingRequestCommand, ValidateFunction<JsonType>>()
this.incomingRequestHandler = this.incomingRequestHandler.bind(this) as <
ReqType extends JsonType,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
- ResType extends JsonType,
+ ResType extends JsonType
>(
chargingStation: ChargingStation,
messageId: string,
commandName: IncomingRequestCommand,
- commandPayload: ReqType,
- ) => Promise<void>;
+ commandPayload: ReqType
+ ) => Promise<void>
this.validateIncomingRequestPayload = this.validateIncomingRequestPayload.bind(this) as <
- T extends JsonType,
+ T extends JsonType
>(
chargingStation: ChargingStation,
commandName: IncomingRequestCommand,
schema: JSONSchemaType<T>,
- payload: T,
- ) => boolean;
+ payload: T
+ ) => boolean
}
public static getInstance<T extends OCPPIncomingRequestService>(this: new () => T): T {
if (OCPPIncomingRequestService.instance === null) {
- OCPPIncomingRequestService.instance = new this();
+ OCPPIncomingRequestService.instance = new this()
}
- return OCPPIncomingRequestService.instance as T;
+ return OCPPIncomingRequestService.instance as T
}
protected handleIncomingRequestError<T extends JsonType>(
chargingStation: ChargingStation,
commandName: IncomingRequestCommand,
error: Error,
- params: HandleErrorParams<T> = { throwError: true, consoleOut: false },
+ params: HandleErrorParams<T> = { throwError: true, consoleOut: false }
): T | undefined {
- setDefaultErrorParams(params);
+ setDefaultErrorParams(params)
logger.error(
`${chargingStation.logPrefix()} ${moduleName}.handleIncomingRequestError: Incoming request command '${commandName}' error:`,
- error,
- );
- if (!params?.throwError && params?.errorResponse) {
- return params?.errorResponse;
+ error
+ )
+ if (params?.throwError === false && params?.errorResponse != null) {
+ return params?.errorResponse
}
- if (params?.throwError && !params?.errorResponse) {
- throw error;
+ if (params?.throwError === true && params?.errorResponse == null) {
+ throw error
}
- if (params?.throwError && params?.errorResponse) {
- return params?.errorResponse;
+ if (params?.throwError === true && params?.errorResponse != null) {
+ return params?.errorResponse
}
}
chargingStation: ChargingStation,
commandName: IncomingRequestCommand,
schema: JSONSchemaType<T>,
- payload: T,
+ payload: T
): boolean {
if (chargingStation.stationInfo?.ocppStrictCompliance === false) {
- return true;
+ return true
}
- const validate = this.getJsonIncomingRequestValidateFunction<T>(commandName, schema);
+ const validate = this.getJsonIncomingRequestValidateFunction<T>(commandName, schema)
if (validate(payload)) {
- return true;
+ return true
}
logger.error(
`${chargingStation.logPrefix()} ${moduleName}.validateIncomingRequestPayload: Command '${commandName}' incoming request PDU is invalid: %j`,
- validate.errors,
- );
+ validate.errors
+ )
throw new OCPPError(
OCPPServiceUtils.ajvErrorsToErrorType(validate.errors),
'Incoming request PDU is invalid',
commandName,
- JSON.stringify(validate.errors, undefined, 2),
- );
+ JSON.stringify(validate.errors, undefined, 2)
+ )
}
- protected handleRequestClearCache(chargingStation: ChargingStation): ClearCacheResponse {
+ protected handleRequestClearCache (chargingStation: ChargingStation): ClearCacheResponse {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
if (chargingStation.idTagsCache.deleteIdTags(getIdTagsFile(chargingStation.stationInfo)!)) {
- return OCPPConstants.OCPP_RESPONSE_ACCEPTED;
+ return OCPPConstants.OCPP_RESPONSE_ACCEPTED
}
- return OCPPConstants.OCPP_RESPONSE_REJECTED;
+ return OCPPConstants.OCPP_RESPONSE_REJECTED
}
private getJsonIncomingRequestValidateFunction<T extends JsonType>(
commandName: IncomingRequestCommand,
- schema: JSONSchemaType<T>,
- ) {
- if (this.jsonValidateFunctions.has(commandName) === false) {
- this.jsonValidateFunctions.set(commandName, this.ajv.compile<T>(schema).bind(this));
+ schema: JSONSchemaType<T>
+ ): ValidateFunction<JsonType> {
+ if (!this.jsonValidateFunctions.has(commandName)) {
+ this.jsonValidateFunctions.set(commandName, this.ajv.compile<T>(schema).bind(this))
}
- return this.jsonValidateFunctions.get(commandName)!;
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ return this.jsonValidateFunctions.get(commandName)!
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
chargingStation: ChargingStation,
messageId: string,
commandName: IncomingRequestCommand,
- commandPayload: ReqType,
- ): Promise<void>;
+ commandPayload: ReqType
+ ): Promise<void>
}
-import _Ajv, { type JSONSchemaType, type ValidateFunction } from 'ajv';
-import _ajvFormats from 'ajv-formats';
+import _Ajv, { type JSONSchemaType, type ValidateFunction } from 'ajv'
+import _ajvFormats from 'ajv-formats'
-import { OCPPConstants } from './OCPPConstants.js';
-import type { OCPPResponseService } from './OCPPResponseService.js';
-import { OCPPServiceUtils } from './OCPPServiceUtils.js';
-import type { ChargingStation } from '../../charging-station/index.js';
-import { OCPPError } from '../../exception/index.js';
-import { PerformanceStatistics } from '../../performance/index.js';
+import { OCPPConstants } from './OCPPConstants.js'
+import type { OCPPResponseService } from './OCPPResponseService.js'
+import { OCPPServiceUtils } from './OCPPServiceUtils.js'
+import type { ChargingStation } from '../../charging-station/index.js'
+import { OCPPError } from '../../exception/index.js'
+import { PerformanceStatistics } from '../../performance/index.js'
import {
ChargingStationEvents,
type ErrorCallback,
type RequestParams,
type Response,
type ResponseCallback,
- type ResponseType,
-} from '../../types/index.js';
+ type ResponseType
+} from '../../types/index.js'
import {
cloneObject,
formatDurationMilliSeconds,
handleSendMessageError,
isNullOrUndefined,
- logger,
-} from '../../utils/index.js';
-type Ajv = _Ajv.default;
-const Ajv = _Ajv.default;
-const ajvFormats = _ajvFormats.default;
+ logger
+} from '../../utils/index.js'
+type Ajv = _Ajv.default
+// eslint-disable-next-line @typescript-eslint/no-redeclare
+const Ajv = _Ajv.default
+const ajvFormats = _ajvFormats.default
-const moduleName = 'OCPPRequestService';
+const moduleName = 'OCPPRequestService'
const defaultRequestParams: RequestParams = {
skipBufferingOnError: false,
triggerMessage: false,
- throwError: false,
-};
+ throwError: false
+}
export abstract class OCPPRequestService {
- private static instance: OCPPRequestService | null = null;
- private readonly version: OCPPVersion;
- private readonly ajv: Ajv;
- private readonly ocppResponseService: OCPPResponseService;
- private readonly jsonValidateFunctions: Map<RequestCommand, ValidateFunction<JsonType>>;
- protected abstract jsonSchemas: Map<RequestCommand, JSONSchemaType<JsonType>>;
+ private static instance: OCPPRequestService | null = null
+ private readonly version: OCPPVersion
+ private readonly ajv: Ajv
+ private readonly ocppResponseService: OCPPResponseService
+ private readonly jsonValidateFunctions: Map<RequestCommand, ValidateFunction<JsonType>>
+ protected abstract jsonSchemas: Map<RequestCommand, JSONSchemaType<JsonType>>
- protected constructor(version: OCPPVersion, ocppResponseService: OCPPResponseService) {
- this.version = version;
+ protected constructor (version: OCPPVersion, ocppResponseService: OCPPResponseService) {
+ this.version = version
this.ajv = new Ajv({
keywords: ['javaType'],
- multipleOfPrecision: 2,
- });
- ajvFormats(this.ajv);
- this.jsonValidateFunctions = new Map<RequestCommand, ValidateFunction<JsonType>>();
- this.ocppResponseService = ocppResponseService;
+ multipleOfPrecision: 2
+ })
+ ajvFormats(this.ajv)
+ this.jsonValidateFunctions = new Map<RequestCommand, ValidateFunction<JsonType>>()
+ this.ocppResponseService = ocppResponseService
this.requestHandler = this.requestHandler.bind(this) as <
// eslint-disable-next-line @typescript-eslint/no-unused-vars
ReqType extends JsonType,
- ResType extends JsonType,
+ ResType extends JsonType
>(
chargingStation: ChargingStation,
commandName: RequestCommand,
commandParams?: JsonType,
- params?: RequestParams,
- ) => Promise<ResType>;
+ params?: RequestParams
+ ) => Promise<ResType>
this.sendMessage = this.sendMessage.bind(this) as (
chargingStation: ChargingStation,
messageId: string,
messagePayload: JsonType,
commandName: RequestCommand,
- params?: RequestParams,
- ) => Promise<ResponseType>;
+ params?: RequestParams
+ ) => Promise<ResponseType>
this.sendResponse = this.sendResponse.bind(this) as (
chargingStation: ChargingStation,
messageId: string,
messagePayload: JsonType,
- commandName: IncomingRequestCommand,
- ) => Promise<ResponseType>;
+ commandName: IncomingRequestCommand
+ ) => Promise<ResponseType>
this.sendError = this.sendError.bind(this) as (
chargingStation: ChargingStation,
messageId: string,
ocppError: OCPPError,
- commandName: RequestCommand | IncomingRequestCommand,
- ) => Promise<ResponseType>;
+ commandName: RequestCommand | IncomingRequestCommand
+ ) => Promise<ResponseType>
this.internalSendMessage = this.internalSendMessage.bind(this) as (
chargingStation: ChargingStation,
messageId: string,
messagePayload: JsonType | OCPPError,
messageType: MessageType,
commandName: RequestCommand | IncomingRequestCommand,
- params?: RequestParams,
- ) => Promise<ResponseType>;
+ params?: RequestParams
+ ) => Promise<ResponseType>
this.buildMessageToSend = this.buildMessageToSend.bind(this) as (
chargingStation: ChargingStation,
messageId: string,
messagePayload: JsonType | OCPPError,
messageType: MessageType,
- commandName: RequestCommand | IncomingRequestCommand,
- ) => string;
+ commandName: RequestCommand | IncomingRequestCommand
+ ) => string
this.validateRequestPayload = this.validateRequestPayload.bind(this) as <T extends JsonType>(
chargingStation: ChargingStation,
commandName: RequestCommand | IncomingRequestCommand,
- payload: T,
- ) => boolean;
+ payload: T
+ ) => boolean
this.validateIncomingRequestResponsePayload = this.validateIncomingRequestResponsePayload.bind(
- this,
+ this
) as <T extends JsonType>(
chargingStation: ChargingStation,
commandName: RequestCommand | IncomingRequestCommand,
- payload: T,
- ) => boolean;
+ payload: T
+ ) => boolean
}
public static getInstance<T extends OCPPRequestService>(
this: new (ocppResponseService: OCPPResponseService) => T,
- ocppResponseService: OCPPResponseService,
+ ocppResponseService: OCPPResponseService
): T {
if (OCPPRequestService.instance === null) {
- OCPPRequestService.instance = new this(ocppResponseService);
+ OCPPRequestService.instance = new this(ocppResponseService)
}
- return OCPPRequestService.instance as T;
+ return OCPPRequestService.instance as T
}
- public async sendResponse(
+ public async sendResponse (
chargingStation: ChargingStation,
messageId: string,
messagePayload: JsonType,
- commandName: IncomingRequestCommand,
+ commandName: IncomingRequestCommand
): Promise<ResponseType> {
try {
// Send response message
messageId,
messagePayload,
MessageType.CALL_RESULT_MESSAGE,
- commandName,
- );
+ commandName
+ )
} catch (error) {
handleSendMessageError(chargingStation, commandName, error as Error, {
- throwError: true,
- });
- return null;
+ throwError: true
+ })
+ return null
}
}
- public async sendError(
+ public async sendError (
chargingStation: ChargingStation,
messageId: string,
ocppError: OCPPError,
- commandName: RequestCommand | IncomingRequestCommand,
+ commandName: RequestCommand | IncomingRequestCommand
): Promise<ResponseType> {
try {
// Send error message
messageId,
ocppError,
MessageType.CALL_ERROR_MESSAGE,
- commandName,
- );
+ commandName
+ )
} catch (error) {
- handleSendMessageError(chargingStation, commandName, error as Error);
- return null;
+ handleSendMessageError(chargingStation, commandName, error as Error)
+ return null
}
}
- protected async sendMessage(
+ protected async sendMessage (
chargingStation: ChargingStation,
messageId: string,
messagePayload: JsonType,
commandName: RequestCommand,
- params?: RequestParams,
+ params?: RequestParams
): Promise<ResponseType> {
params = {
...defaultRequestParams,
- ...params,
- };
+ ...params
+ }
try {
return await this.internalSendMessage(
chargingStation,
messagePayload,
MessageType.CALL_MESSAGE,
commandName,
- params,
- );
+ params
+ )
} catch (error) {
handleSendMessageError(chargingStation, commandName, error as Error, {
- throwError: params.throwError,
- });
- return null;
+ throwError: params.throwError
+ })
+ return null
}
}
private validateRequestPayload<T extends JsonType>(
chargingStation: ChargingStation,
commandName: RequestCommand | IncomingRequestCommand,
- payload: T,
+ payload: T
): boolean {
if (chargingStation.stationInfo?.ocppStrictCompliance === false) {
- return true;
+ return true
}
- if (this.jsonSchemas.has(commandName as RequestCommand) === false) {
+ if (!this.jsonSchemas.has(commandName as RequestCommand)) {
logger.warn(
- `${chargingStation.logPrefix()} ${moduleName}.validateRequestPayload: No JSON schema found for command '${commandName}' PDU validation`,
- );
- return true;
+ `${chargingStation.logPrefix()} ${moduleName}.validateRequestPayload: No JSON schema found for command '${commandName}' PDU validation`
+ )
+ return true
}
- const validate = this.getJsonRequestValidateFunction<T>(commandName as RequestCommand);
- payload = cloneObject<T>(payload);
- OCPPServiceUtils.convertDateToISOString<T>(payload);
+ const validate = this.getJsonRequestValidateFunction<T>(commandName as RequestCommand)
+ payload = cloneObject<T>(payload)
+ OCPPServiceUtils.convertDateToISOString<T>(payload)
if (validate(payload)) {
- return true;
+ return true
}
logger.error(
`${chargingStation.logPrefix()} ${moduleName}.validateRequestPayload: Command '${commandName}' request PDU is invalid: %j`,
- validate.errors,
- );
+ validate.errors
+ )
// OCPPError usage here is debatable: it's an error in the OCPP stack but not targeted to sendError().
throw new OCPPError(
OCPPServiceUtils.ajvErrorsToErrorType(validate.errors),
'Request PDU is invalid',
commandName,
- JSON.stringify(validate.errors, undefined, 2),
- );
+ JSON.stringify(validate.errors, undefined, 2)
+ )
}
- private getJsonRequestValidateFunction<T extends JsonType>(commandName: RequestCommand) {
- if (this.jsonValidateFunctions.has(commandName) === false) {
+ private getJsonRequestValidateFunction<T extends JsonType>(
+ commandName: RequestCommand
+ ): ValidateFunction<JsonType> {
+ if (!this.jsonValidateFunctions.has(commandName)) {
this.jsonValidateFunctions.set(
commandName,
- this.ajv.compile<T>(this.jsonSchemas.get(commandName)!).bind(this),
- );
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ this.ajv.compile<T>(this.jsonSchemas.get(commandName)!).bind(this)
+ )
}
- return this.jsonValidateFunctions.get(commandName)!;
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ return this.jsonValidateFunctions.get(commandName)!
}
private validateIncomingRequestResponsePayload<T extends JsonType>(
chargingStation: ChargingStation,
commandName: RequestCommand | IncomingRequestCommand,
- payload: T,
+ payload: T
): boolean {
if (chargingStation.stationInfo?.ocppStrictCompliance === false) {
- return true;
+ return true
}
if (
- this.ocppResponseService.jsonIncomingRequestResponseSchemas.has(
- commandName as IncomingRequestCommand,
- ) === false
+ !this.ocppResponseService.jsonIncomingRequestResponseSchemas.has(
+ commandName as IncomingRequestCommand
+ )
) {
logger.warn(
- `${chargingStation.logPrefix()} ${moduleName}.validateIncomingRequestResponsePayload: No JSON schema found for command '${commandName}' PDU validation`,
- );
- return true;
+ `${chargingStation.logPrefix()} ${moduleName}.validateIncomingRequestResponsePayload: No JSON schema found for command '${commandName}' PDU validation`
+ )
+ return true
}
const validate = this.getJsonRequestResponseValidateFunction<T>(
- commandName as IncomingRequestCommand,
- );
- payload = cloneObject<T>(payload);
- OCPPServiceUtils.convertDateToISOString<T>(payload);
+ commandName as IncomingRequestCommand
+ )
+ payload = cloneObject<T>(payload)
+ OCPPServiceUtils.convertDateToISOString<T>(payload)
if (validate(payload)) {
- return true;
+ return true
}
logger.error(
`${chargingStation.logPrefix()} ${moduleName}.validateIncomingRequestResponsePayload: Command '${commandName}' reponse PDU is invalid: %j`,
- validate.errors,
- );
+ validate.errors
+ )
// OCPPError usage here is debatable: it's an error in the OCPP stack but not targeted to sendError().
throw new OCPPError(
OCPPServiceUtils.ajvErrorsToErrorType(validate.errors),
'Response PDU is invalid',
commandName,
- JSON.stringify(validate.errors, undefined, 2),
- );
+ JSON.stringify(validate.errors, undefined, 2)
+ )
}
private getJsonRequestResponseValidateFunction<T extends JsonType>(
- commandName: IncomingRequestCommand,
- ) {
- if (
- this.ocppResponseService.jsonIncomingRequestResponseValidateFunctions.has(commandName) ===
- false
- ) {
+ commandName: IncomingRequestCommand
+ ): ValidateFunction<JsonType> {
+ if (!this.ocppResponseService.jsonIncomingRequestResponseValidateFunctions.has(commandName)) {
this.ocppResponseService.jsonIncomingRequestResponseValidateFunctions.set(
commandName,
this.ajv
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
.compile<T>(this.ocppResponseService.jsonIncomingRequestResponseSchemas.get(commandName)!)
- .bind(this),
- );
+ .bind(this)
+ )
}
- return this.ocppResponseService.jsonIncomingRequestResponseValidateFunctions.get(commandName)!;
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ return this.ocppResponseService.jsonIncomingRequestResponseValidateFunctions.get(commandName)!
}
- private async internalSendMessage(
+ private async internalSendMessage (
chargingStation: ChargingStation,
messageId: string,
messagePayload: JsonType | OCPPError,
messageType: MessageType,
commandName: RequestCommand | IncomingRequestCommand,
- params?: RequestParams,
+ params?: RequestParams
): Promise<ResponseType> {
params = {
...defaultRequestParams,
- ...params,
- };
+ ...params
+ }
if (
- (chargingStation.inUnknownState() === true &&
- commandName === RequestCommand.BOOT_NOTIFICATION) ||
+ (chargingStation.inUnknownState() && commandName === RequestCommand.BOOT_NOTIFICATION) ||
(chargingStation.stationInfo?.ocppStrictCompliance === false &&
- chargingStation.inUnknownState() === true) ||
- chargingStation.inAcceptedState() === true ||
- (chargingStation.inPendingState() === true &&
+ chargingStation.inUnknownState()) ||
+ chargingStation.inAcceptedState() ||
+ (chargingStation.inPendingState() &&
(params.triggerMessage === true || messageType === MessageType.CALL_RESULT_MESSAGE))
) {
// eslint-disable-next-line @typescript-eslint/no-this-alias
- const self = this;
+ const self = this
// Send a message through wsConnection
- return new Promise<ResponseType>((resolve, reject) => {
+ return await new Promise<ResponseType>((resolve, reject) => {
/**
* Function that will receive the request's response
*
if (chargingStation.stationInfo?.enableStatistics === true) {
chargingStation.performanceStatistics?.addRequestStatistic(
commandName,
- MessageType.CALL_RESULT_MESSAGE,
- );
+ MessageType.CALL_RESULT_MESSAGE
+ )
}
// Handle the request's response
self.ocppResponseService
chargingStation,
commandName as RequestCommand,
payload,
- requestPayload,
+ requestPayload
)
.then(() => {
- resolve(payload);
+ resolve(payload)
})
.catch(reject)
.finally(() => {
- chargingStation.requests.delete(messageId);
- chargingStation.emit(ChargingStationEvents.updated);
- });
- };
+ chargingStation.requests.delete(messageId)
+ chargingStation.emit(ChargingStationEvents.updated)
+ })
+ }
/**
* Function that will receive the request's error response
* @param requestStatistic -
*/
const errorCallback = (ocppError: OCPPError, requestStatistic = true): void => {
- if (requestStatistic === true && chargingStation.stationInfo?.enableStatistics === true) {
+ if (requestStatistic && chargingStation.stationInfo?.enableStatistics === true) {
chargingStation.performanceStatistics?.addRequestStatistic(
commandName,
- MessageType.CALL_ERROR_MESSAGE,
- );
+ MessageType.CALL_ERROR_MESSAGE
+ )
}
logger.error(
`${chargingStation.logPrefix()} Error occurred at ${OCPPServiceUtils.getMessageTypeString(
- messageType,
+ messageType
)} command ${commandName} with PDU %j:`,
messagePayload,
- ocppError,
- );
- chargingStation.requests.delete(messageId);
- chargingStation.emit(ChargingStationEvents.updated);
- reject(ocppError);
- };
+ ocppError
+ )
+ chargingStation.requests.delete(messageId)
+ chargingStation.emit(ChargingStationEvents.updated)
+ reject(ocppError)
+ }
const handleSendError = (ocppError: OCPPError): void => {
if (params?.skipBufferingOnError === false) {
// Buffer
- chargingStation.bufferMessage(messageToSend);
+ chargingStation.bufferMessage(messageToSend)
if (messageType === MessageType.CALL_MESSAGE) {
this.cacheRequestPromise(
chargingStation,
messagePayload as JsonType,
commandName,
responseCallback,
- errorCallback,
- );
+ errorCallback
+ )
}
} else if (
params?.skipBufferingOnError === true &&
messageType === MessageType.CALL_MESSAGE
) {
// Remove request from the cache
- chargingStation.requests.delete(messageId);
+ chargingStation.requests.delete(messageId)
}
- return reject(ocppError);
- };
+ reject(ocppError)
+ }
if (chargingStation.stationInfo?.enableStatistics === true) {
- chargingStation.performanceStatistics?.addRequestStatistic(commandName, messageType);
+ chargingStation.performanceStatistics?.addRequestStatistic(commandName, messageType)
}
const messageToSend = this.buildMessageToSend(
chargingStation,
messageId,
messagePayload,
messageType,
- commandName,
- );
+ commandName
+ )
// Check if wsConnection opened
- if (chargingStation.isWebSocketConnectionOpened() === true) {
- const beginId = PerformanceStatistics.beginMeasure(commandName);
+ if (chargingStation.isWebSocketConnectionOpened()) {
+ const beginId = PerformanceStatistics.beginMeasure(commandName)
const sendTimeout = setTimeout(() => {
- return handleSendError(
+ handleSendError(
new OCPPError(
ErrorType.GENERIC_ERROR,
`Timeout ${formatDurationMilliSeconds(
- OCPPConstants.OCPP_WEBSOCKET_TIMEOUT,
+ OCPPConstants.OCPP_WEBSOCKET_TIMEOUT
)} reached for ${
params?.skipBufferingOnError === false ? '' : 'non '
}buffered message id '${messageId}' with content '${messageToSend}'`,
commandName,
- (messagePayload as OCPPError).details,
- ),
- );
- }, OCPPConstants.OCPP_WEBSOCKET_TIMEOUT);
+ (messagePayload as OCPPError).details
+ )
+ )
+ }, OCPPConstants.OCPP_WEBSOCKET_TIMEOUT)
chargingStation.wsConnection?.send(messageToSend, (error?: Error) => {
- PerformanceStatistics.endMeasure(commandName, beginId);
- clearTimeout(sendTimeout);
+ PerformanceStatistics.endMeasure(commandName, beginId)
+ clearTimeout(sendTimeout)
if (isNullOrUndefined(error)) {
logger.debug(
`${chargingStation.logPrefix()} >> Command '${commandName}' sent ${OCPPServiceUtils.getMessageTypeString(
- messageType,
- )} payload: ${messageToSend}`,
- );
+ messageType
+ )} payload: ${messageToSend}`
+ )
if (messageType === MessageType.CALL_MESSAGE) {
this.cacheRequestPromise(
chargingStation,
messagePayload as JsonType,
commandName,
responseCallback,
- errorCallback,
- );
+ errorCallback
+ )
} else {
// Resolve response
- return resolve(messagePayload);
+ resolve(messagePayload)
}
- } else if (error) {
- return handleSendError(
+ } else if (error != null) {
+ handleSendError(
new OCPPError(
ErrorType.GENERIC_ERROR,
`WebSocket errored for ${
params?.skipBufferingOnError === false ? '' : 'non '
}buffered message id '${messageId}' with content '${messageToSend}'`,
commandName,
- { name: error.name, message: error.message, stack: error.stack },
- ),
- );
+ { name: error.name, message: error.message, stack: error.stack }
+ )
+ )
}
- });
+ })
} else {
- return handleSendError(
+ handleSendError(
new OCPPError(
ErrorType.GENERIC_ERROR,
`WebSocket closed for ${
params?.skipBufferingOnError === false ? '' : 'non '
}buffered message id '${messageId}' with content '${messageToSend}'`,
commandName,
- (messagePayload as OCPPError).details,
- ),
- );
+ (messagePayload as OCPPError).details
+ )
+ )
}
- });
+ })
}
throw new OCPPError(
ErrorType.SECURITY_ERROR,
`Cannot send command ${commandName} PDU when the charging station is in ${chargingStation?.bootNotificationResponse?.status} state on the central server`,
- commandName,
- );
+ commandName
+ )
}
- private buildMessageToSend(
+ private buildMessageToSend (
chargingStation: ChargingStation,
messageId: string,
messagePayload: JsonType | OCPPError,
messageType: MessageType,
- commandName: RequestCommand | IncomingRequestCommand,
+ commandName: RequestCommand | IncomingRequestCommand
): string {
- let messageToSend: string;
+ let messageToSend: string
// Type of message
switch (messageType) {
// Request
case MessageType.CALL_MESSAGE:
// Build request
- this.validateRequestPayload(chargingStation, commandName, messagePayload as JsonType);
+ this.validateRequestPayload(chargingStation, commandName, messagePayload as JsonType)
messageToSend = JSON.stringify([
messageType,
messageId,
commandName,
- messagePayload,
- ] as OutgoingRequest);
- break;
+ messagePayload
+ ] as OutgoingRequest)
+ break
// Response
case MessageType.CALL_RESULT_MESSAGE:
// Build response
this.validateIncomingRequestResponsePayload(
chargingStation,
commandName,
- messagePayload as JsonType,
- );
- messageToSend = JSON.stringify([messageType, messageId, messagePayload] as Response);
- break;
+ messagePayload as JsonType
+ )
+ messageToSend = JSON.stringify([messageType, messageId, messagePayload] as Response)
+ break
// Error Message
case MessageType.CALL_ERROR_MESSAGE:
// Build Error Message
(messagePayload as OCPPError).code,
(messagePayload as OCPPError).message,
(messagePayload as OCPPError).details ?? {
- command: (messagePayload as OCPPError).command ?? commandName,
- },
- ] as ErrorResponse);
- break;
+ command: (messagePayload as OCPPError).command ?? commandName
+ }
+ ] as ErrorResponse)
+ break
}
- return messageToSend;
+ return messageToSend
}
- private cacheRequestPromise(
+ private cacheRequestPromise (
chargingStation: ChargingStation,
messageId: string,
messagePayload: JsonType,
commandName: RequestCommand | IncomingRequestCommand,
responseCallback: ResponseCallback,
- errorCallback: ErrorCallback,
+ errorCallback: ErrorCallback
): void {
chargingStation.requests.set(messageId, [
responseCallback,
errorCallback,
commandName,
- messagePayload,
- ]);
+ messagePayload
+ ])
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
commandName: RequestCommand,
// FIXME: should be ReqType
commandParams?: JsonType,
- params?: RequestParams,
- ): Promise<ResType>;
+ params?: RequestParams
+ ): Promise<ResType>
}
-import _Ajv, { type JSONSchemaType, type ValidateFunction } from 'ajv';
-import _ajvFormats from 'ajv-formats';
+import _Ajv, { type JSONSchemaType, type ValidateFunction } from 'ajv'
+import _ajvFormats from 'ajv-formats'
-import { OCPPServiceUtils } from './OCPPServiceUtils.js';
-import type { ChargingStation } from '../../charging-station/index.js';
-import { OCPPError } from '../../exception/index.js';
+import { OCPPServiceUtils } from './OCPPServiceUtils.js'
+import type { ChargingStation } from '../../charging-station/index.js'
+import { OCPPError } from '../../exception/index.js'
import type {
IncomingRequestCommand,
JsonType,
OCPPVersion,
- RequestCommand,
-} from '../../types/index.js';
-import { logger } from '../../utils/index.js';
-type Ajv = _Ajv.default;
-const Ajv = _Ajv.default;
-const ajvFormats = _ajvFormats.default;
+ RequestCommand
+} from '../../types/index.js'
+import { logger } from '../../utils/index.js'
+type Ajv = _Ajv.default
+// eslint-disable-next-line @typescript-eslint/no-redeclare
+const Ajv = _Ajv.default
+const ajvFormats = _ajvFormats.default
-const moduleName = 'OCPPResponseService';
+const moduleName = 'OCPPResponseService'
export abstract class OCPPResponseService {
- private static instance: OCPPResponseService | null = null;
+ private static instance: OCPPResponseService | null = null
public jsonIncomingRequestResponseValidateFunctions: Map<
- IncomingRequestCommand,
- ValidateFunction<JsonType>
- >;
+ IncomingRequestCommand,
+ ValidateFunction<JsonType>
+ >
- private readonly version: OCPPVersion;
- private readonly ajv: Ajv;
- private jsonRequestValidateFunctions: Map<RequestCommand, ValidateFunction<JsonType>>;
+ private readonly version: OCPPVersion
+ private readonly ajv: Ajv
+ private readonly jsonRequestValidateFunctions: Map<RequestCommand, ValidateFunction<JsonType>>
public abstract jsonIncomingRequestResponseSchemas: Map<
- IncomingRequestCommand,
- JSONSchemaType<JsonType>
- >;
+ IncomingRequestCommand,
+ JSONSchemaType<JsonType>
+ >
- protected constructor(version: OCPPVersion) {
- this.version = version;
+ protected constructor (version: OCPPVersion) {
+ this.version = version
this.ajv = new Ajv({
keywords: ['javaType'],
- multipleOfPrecision: 2,
- });
- ajvFormats(this.ajv);
- this.jsonRequestValidateFunctions = new Map<RequestCommand, ValidateFunction<JsonType>>();
+ multipleOfPrecision: 2
+ })
+ ajvFormats(this.ajv)
+ this.jsonRequestValidateFunctions = new Map<RequestCommand, ValidateFunction<JsonType>>()
this.jsonIncomingRequestResponseValidateFunctions = new Map<
- IncomingRequestCommand,
- ValidateFunction<JsonType>
- >();
+ IncomingRequestCommand,
+ ValidateFunction<JsonType>
+ >()
this.responseHandler = this.responseHandler.bind(this) as <
ReqType extends JsonType,
- ResType extends JsonType,
+ ResType extends JsonType
>(
chargingStation: ChargingStation,
commandName: RequestCommand,
payload: ResType,
- requestPayload: ReqType,
- ) => Promise<void>;
+ requestPayload: ReqType
+ ) => Promise<void>
this.validateResponsePayload = this.validateResponsePayload.bind(this) as <T extends JsonType>(
chargingStation: ChargingStation,
commandName: RequestCommand,
schema: JSONSchemaType<T>,
- payload: T,
- ) => boolean;
+ payload: T
+ ) => boolean
}
public static getInstance<T extends OCPPResponseService>(this: new () => T): T {
if (OCPPResponseService.instance === null) {
- OCPPResponseService.instance = new this();
+ OCPPResponseService.instance = new this()
}
- return OCPPResponseService.instance as T;
+ return OCPPResponseService.instance as T
}
protected validateResponsePayload<T extends JsonType>(
chargingStation: ChargingStation,
commandName: RequestCommand,
schema: JSONSchemaType<T>,
- payload: T,
+ payload: T
): boolean {
if (chargingStation.stationInfo?.ocppStrictCompliance === false) {
- return true;
+ return true
}
- const validate = this.getJsonRequestValidateFunction<T>(commandName, schema);
+ const validate = this.getJsonRequestValidateFunction<T>(commandName, schema)
if (validate(payload)) {
- return true;
+ return true
}
logger.error(
`${chargingStation.logPrefix()} ${moduleName}.validateResponsePayload: Command '${commandName}' response PDU is invalid: %j`,
- validate.errors,
- );
+ validate.errors
+ )
throw new OCPPError(
OCPPServiceUtils.ajvErrorsToErrorType(validate.errors),
'Response PDU is invalid',
commandName,
- JSON.stringify(validate.errors, undefined, 2),
- );
+ JSON.stringify(validate.errors, undefined, 2)
+ )
}
- protected emptyResponseHandler() {
+ protected emptyResponseHandler (): void {
/* This is intentional */
}
private getJsonRequestValidateFunction<T extends JsonType>(
commandName: RequestCommand,
- schema: JSONSchemaType<T>,
- ) {
- if (this.jsonRequestValidateFunctions.has(commandName) === false) {
- this.jsonRequestValidateFunctions.set(commandName, this.ajv.compile<T>(schema).bind(this));
+ schema: JSONSchemaType<T>
+ ): ValidateFunction<JsonType> {
+ if (!this.jsonRequestValidateFunctions.has(commandName)) {
+ this.jsonRequestValidateFunctions.set(commandName, this.ajv.compile<T>(schema).bind(this))
}
- return this.jsonRequestValidateFunctions.get(commandName)!;
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ return this.jsonRequestValidateFunctions.get(commandName)!
}
public abstract responseHandler<ReqType extends JsonType, ResType extends JsonType>(
chargingStation: ChargingStation,
commandName: RequestCommand,
payload: ResType,
- requestPayload: ReqType,
- ): Promise<void>;
+ requestPayload: ReqType
+ ): Promise<void>
}
-import { readFileSync } from 'node:fs';
-import { dirname, join } from 'node:path';
-import { fileURLToPath } from 'node:url';
+import { readFileSync } from 'node:fs'
+import { dirname, join } from 'node:path'
+import { fileURLToPath } from 'node:url'
-import type { DefinedError, ErrorObject, JSONSchemaType } from 'ajv';
-import { isDate } from 'date-fns';
+import type { DefinedError, ErrorObject, JSONSchemaType } from 'ajv'
+import { isDate } from 'date-fns'
-import { OCPP16Constants } from './1.6/OCPP16Constants.js';
-import { OCPP20Constants } from './2.0/OCPP20Constants.js';
-import { OCPPConstants } from './OCPPConstants.js';
+import { OCPP16Constants } from './1.6/OCPP16Constants.js'
+import { OCPP20Constants } from './2.0/OCPP20Constants.js'
+import { OCPPConstants } from './OCPPConstants.js'
import {
type ChargingStation,
getConfigurationKey,
- getIdTagsFile,
-} from '../../charging-station/index.js';
-import { BaseError, OCPPError } from '../../exception/index.js';
+ getIdTagsFile
+} from '../../charging-station/index.js'
+import { BaseError, OCPPError } from '../../exception/index.js'
import {
AuthorizationStatus,
type AuthorizeRequest,
type SampledValueTemplate,
StandardParametersKey,
type StatusNotificationRequest,
- type StatusNotificationResponse,
-} from '../../types/index.js';
+ type StatusNotificationResponse
+} from '../../types/index.js'
import {
ACElectricUtils,
Constants,
logger,
max,
min,
- roundTo,
-} from '../../utils/index.js';
+ roundTo
+} from '../../utils/index.js'
export const getMessageTypeString = (messageType: MessageType): string => {
switch (messageType) {
case MessageType.CALL_MESSAGE:
- return 'request';
+ return 'request'
case MessageType.CALL_RESULT_MESSAGE:
- return 'response';
+ return 'response'
case MessageType.CALL_ERROR_MESSAGE:
- return 'error';
+ return 'error'
default:
- return 'unknown';
+ return 'unknown'
}
-};
+}
export const buildStatusNotificationRequest = (
chargingStation: ChargingStation,
connectorId: number,
status: ConnectorStatusEnum,
- evseId?: number,
+ evseId?: number
): StatusNotificationRequest => {
switch (chargingStation.stationInfo?.ocppVersion) {
case OCPPVersion.VERSION_16:
return {
connectorId,
status,
- errorCode: ChargePointErrorCode.NO_ERROR,
- } as OCPP16StatusNotificationRequest;
+ errorCode: ChargePointErrorCode.NO_ERROR
+ } satisfies OCPP16StatusNotificationRequest
case OCPPVersion.VERSION_20:
case OCPPVersion.VERSION_201:
return {
timestamp: new Date(),
connectorStatus: status,
connectorId,
- evseId,
- } as OCPP20StatusNotificationRequest;
+ evseId
+ } satisfies OCPP20StatusNotificationRequest
default:
- throw new BaseError('Cannot build status notification payload: OCPP version not supported');
+ throw new BaseError('Cannot build status notification payload: OCPP version not supported')
}
-};
+}
export const isIdTagAuthorized = async (
chargingStation: ChargingStation,
connectorId: number,
- idTag: string,
+ idTag: string
): Promise<boolean> => {
if (
!chargingStation.getLocalAuthListEnabled() &&
- !chargingStation.stationInfo?.remoteAuthorization
+ chargingStation.stationInfo?.remoteAuthorization === false
) {
logger.warn(
- `${chargingStation.logPrefix()} The charging station expects to authorize RFID tags but nor local authorization nor remote authorization are enabled. Misbehavior may occur`,
- );
+ `${chargingStation.logPrefix()} The charging station expects to authorize RFID tags but nor local authorization nor remote authorization are enabled. Misbehavior may occur`
+ )
}
- if (
- chargingStation.getLocalAuthListEnabled() === true &&
- isIdTagLocalAuthorized(chargingStation, idTag)
- ) {
- const connectorStatus: ConnectorStatus = chargingStation.getConnectorStatus(connectorId)!;
- connectorStatus.localAuthorizeIdTag = idTag;
- connectorStatus.idTagLocalAuthorized = true;
- return true;
- } else if (chargingStation.stationInfo?.remoteAuthorization) {
- return await isIdTagRemoteAuthorized(chargingStation, connectorId, idTag);
+ if (chargingStation.getLocalAuthListEnabled() && isIdTagLocalAuthorized(chargingStation, idTag)) {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ const connectorStatus: ConnectorStatus = chargingStation.getConnectorStatus(connectorId)!
+ connectorStatus.localAuthorizeIdTag = idTag
+ connectorStatus.idTagLocalAuthorized = true
+ return true
+ } else if (chargingStation.stationInfo?.remoteAuthorization === true) {
+ return await isIdTagRemoteAuthorized(chargingStation, connectorId, idTag)
}
- return false;
-};
+ return false
+}
const isIdTagLocalAuthorized = (chargingStation: ChargingStation, idTag: string): boolean => {
return (
- chargingStation.hasIdTags() === true &&
+ chargingStation.hasIdTags() &&
isNotEmptyString(
chargingStation.idTagsCache
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
.getIdTags(getIdTagsFile(chargingStation.stationInfo)!)
- ?.find((tag) => tag === idTag),
+ ?.find((tag) => tag === idTag)
)
- );
-};
+ )
+}
const isIdTagRemoteAuthorized = async (
chargingStation: ChargingStation,
connectorId: number,
- idTag: string,
+ idTag: string
): Promise<boolean> => {
- chargingStation.getConnectorStatus(connectorId)!.authorizeIdTag = idTag;
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ chargingStation.getConnectorStatus(connectorId)!.authorizeIdTag = idTag
return (
(
await chargingStation.ocppRequestService.requestHandler<AuthorizeRequest, AuthorizeResponse>(
chargingStation,
RequestCommand.AUTHORIZE,
{
- idTag,
- },
+ idTag
+ }
)
)?.idTagInfo?.status === AuthorizationStatus.ACCEPTED
- );
-};
+ )
+}
export const sendAndSetConnectorStatus = async (
chargingStation: ChargingStation,
connectorId: number,
status: ConnectorStatusEnum,
evseId?: number,
- options?: { send: boolean },
+ options?: { send: boolean }
): Promise<void> => {
- options = { send: true, ...options };
+ options = { send: true, ...options }
if (options.send) {
- checkConnectorStatusTransition(chargingStation, connectorId, status);
+ checkConnectorStatusTransition(chargingStation, connectorId, status)
await chargingStation.ocppRequestService.requestHandler<
- StatusNotificationRequest,
- StatusNotificationResponse
+ StatusNotificationRequest,
+ StatusNotificationResponse
>(
chargingStation,
RequestCommand.STATUS_NOTIFICATION,
- buildStatusNotificationRequest(chargingStation, connectorId, status, evseId),
- );
+ buildStatusNotificationRequest(chargingStation, connectorId, status, evseId)
+ )
}
- chargingStation.getConnectorStatus(connectorId)!.status = status;
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ chargingStation.getConnectorStatus(connectorId)!.status = status
chargingStation.emit(ChargingStationEvents.connectorStatusChanged, {
connectorId,
- ...chargingStation.getConnectorStatus(connectorId),
- });
-};
+ ...chargingStation.getConnectorStatus(connectorId)
+ })
+}
const checkConnectorStatusTransition = (
chargingStation: ChargingStation,
connectorId: number,
- status: ConnectorStatusEnum,
+ status: ConnectorStatusEnum
): boolean => {
- const fromStatus = chargingStation.getConnectorStatus(connectorId)!.status;
- let transitionAllowed = false;
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ const fromStatus = chargingStation.getConnectorStatus(connectorId)!.status
+ let transitionAllowed = false
switch (chargingStation.stationInfo?.ocppVersion) {
case OCPPVersion.VERSION_16:
if (
(connectorId === 0 &&
OCPP16Constants.ChargePointStatusChargingStationTransitions.findIndex(
- (transition) => transition.from === fromStatus && transition.to === status,
+ (transition) => transition.from === fromStatus && transition.to === status
) !== -1) ||
(connectorId > 0 &&
OCPP16Constants.ChargePointStatusConnectorTransitions.findIndex(
- (transition) => transition.from === fromStatus && transition.to === status,
+ (transition) => transition.from === fromStatus && transition.to === status
) !== -1)
) {
- transitionAllowed = true;
+ transitionAllowed = true
}
- break;
+ break
case OCPPVersion.VERSION_20:
case OCPPVersion.VERSION_201:
if (
(connectorId === 0 &&
OCPP20Constants.ChargingStationStatusTransitions.findIndex(
- (transition) => transition.from === fromStatus && transition.to === status,
+ (transition) => transition.from === fromStatus && transition.to === status
) !== -1) ||
(connectorId > 0 &&
OCPP20Constants.ConnectorStatusTransitions.findIndex(
- (transition) => transition.from === fromStatus && transition.to === status,
+ (transition) => transition.from === fromStatus && transition.to === status
) !== -1)
) {
- transitionAllowed = true;
+ transitionAllowed = true
}
- break;
+ break
default:
throw new BaseError(
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
- `Cannot check connector status transition: OCPP version ${chargingStation.stationInfo?.ocppVersion} not supported`,
- );
+ `Cannot check connector status transition: OCPP version ${chargingStation.stationInfo?.ocppVersion} not supported`
+ )
}
- if (transitionAllowed === false) {
+ if (!transitionAllowed) {
logger.warn(
`${chargingStation.logPrefix()} OCPP ${chargingStation.stationInfo
?.ocppVersion} connector id ${connectorId} status transition from '${
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
chargingStation.getConnectorStatus(connectorId)!.status
- }' to '${status}' is not allowed`,
- );
+ }' to '${status}' is not allowed`
+ )
}
- return transitionAllowed;
-};
+ return transitionAllowed
+}
export const buildMeterValue = (
chargingStation: ChargingStation,
connectorId: number,
transactionId: number,
interval: number,
- debug = false,
+ debug = false
): MeterValue => {
- const connector = chargingStation.getConnectorStatus(connectorId);
- let meterValue: MeterValue;
- let socSampledValueTemplate: SampledValueTemplate | undefined;
- let voltageSampledValueTemplate: SampledValueTemplate | undefined;
- let powerSampledValueTemplate: SampledValueTemplate | undefined;
- let powerPerPhaseSampledValueTemplates: MeasurandPerPhaseSampledValueTemplates = {};
- let currentSampledValueTemplate: SampledValueTemplate | undefined;
- let currentPerPhaseSampledValueTemplates: MeasurandPerPhaseSampledValueTemplates = {};
- let energySampledValueTemplate: SampledValueTemplate | undefined;
+ const connector = chargingStation.getConnectorStatus(connectorId)
+ let meterValue: MeterValue
+ let socSampledValueTemplate: SampledValueTemplate | undefined
+ let voltageSampledValueTemplate: SampledValueTemplate | undefined
+ let powerSampledValueTemplate: SampledValueTemplate | undefined
+ let powerPerPhaseSampledValueTemplates: MeasurandPerPhaseSampledValueTemplates = {}
+ let currentSampledValueTemplate: SampledValueTemplate | undefined
+ let currentPerPhaseSampledValueTemplates: MeasurandPerPhaseSampledValueTemplates = {}
+ let energySampledValueTemplate: SampledValueTemplate | undefined
switch (chargingStation.stationInfo?.ocppVersion) {
case OCPPVersion.VERSION_16:
meterValue = {
timestamp: new Date(),
- sampledValue: [],
- };
+ sampledValue: []
+ }
// SoC measurand
socSampledValueTemplate = getSampledValueTemplate(
chargingStation,
connectorId,
- MeterValueMeasurand.STATE_OF_CHARGE,
- );
- if (socSampledValueTemplate) {
- const socMaximumValue = 100;
- const socMinimumValue = socSampledValueTemplate.minimumValue ?? 0;
+ MeterValueMeasurand.STATE_OF_CHARGE
+ )
+ if (socSampledValueTemplate != null) {
+ const socMaximumValue = 100
+ const socMinimumValue = socSampledValueTemplate.minimumValue ?? 0
const socSampledValueTemplateValue = isNotEmptyString(socSampledValueTemplate.value)
? getRandomFloatFluctuatedRounded(
- parseInt(socSampledValueTemplate.value),
- socSampledValueTemplate.fluctuationPercent ?? Constants.DEFAULT_FLUCTUATION_PERCENT,
- )
- : getRandomInteger(socMaximumValue, socMinimumValue);
+ parseInt(socSampledValueTemplate.value),
+ socSampledValueTemplate.fluctuationPercent ?? Constants.DEFAULT_FLUCTUATION_PERCENT
+ )
+ : getRandomInteger(socMaximumValue, socMinimumValue)
meterValue.sampledValue.push(
- buildSampledValue(socSampledValueTemplate, socSampledValueTemplateValue),
- );
- const sampledValuesIndex = meterValue.sampledValue.length - 1;
+ buildSampledValue(socSampledValueTemplate, socSampledValueTemplateValue)
+ )
+ const sampledValuesIndex = meterValue.sampledValue.length - 1
if (
convertToInt(meterValue.sampledValue[sampledValuesIndex].value) > socMaximumValue ||
convertToInt(meterValue.sampledValue[sampledValuesIndex].value) < socMinimumValue ||
MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER
}: connector id ${connectorId}, transaction id ${connector?.transactionId}, value: ${socMinimumValue}/${
meterValue.sampledValue[sampledValuesIndex].value
- }/${socMaximumValue}`,
- );
+ }/${socMaximumValue}`
+ )
}
}
// Voltage measurand
voltageSampledValueTemplate = getSampledValueTemplate(
chargingStation,
connectorId,
- MeterValueMeasurand.VOLTAGE,
- );
- if (voltageSampledValueTemplate) {
+ MeterValueMeasurand.VOLTAGE
+ )
+ if (voltageSampledValueTemplate != null) {
const voltageSampledValueTemplateValue = isNotEmptyString(voltageSampledValueTemplate.value)
? parseInt(voltageSampledValueTemplate.value)
- : chargingStation.stationInfo.voltageOut!;
+ : // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ chargingStation.stationInfo.voltageOut!
const fluctuationPercent =
- voltageSampledValueTemplate.fluctuationPercent ?? Constants.DEFAULT_FLUCTUATION_PERCENT;
+ voltageSampledValueTemplate.fluctuationPercent ?? Constants.DEFAULT_FLUCTUATION_PERCENT
const voltageMeasurandValue = getRandomFloatFluctuatedRounded(
voltageSampledValueTemplateValue,
- fluctuationPercent,
- );
+ fluctuationPercent
+ )
if (
chargingStation.getNumberOfPhases() !== 3 ||
(chargingStation.getNumberOfPhases() === 3 &&
- chargingStation.stationInfo?.mainVoltageMeterValues)
+ chargingStation.stationInfo?.mainVoltageMeterValues === true)
) {
meterValue.sampledValue.push(
- buildSampledValue(voltageSampledValueTemplate, voltageMeasurandValue),
- );
+ buildSampledValue(voltageSampledValueTemplate, voltageMeasurandValue)
+ )
}
for (
let phase = 1;
chargingStation.getNumberOfPhases() === 3 && phase <= chargingStation.getNumberOfPhases();
phase++
) {
- const phaseLineToNeutralValue = `L${phase}-N`;
+ const phaseLineToNeutralValue = `L${phase}-N`
const voltagePhaseLineToNeutralSampledValueTemplate = getSampledValueTemplate(
chargingStation,
connectorId,
MeterValueMeasurand.VOLTAGE,
- phaseLineToNeutralValue as MeterValuePhase,
- );
- let voltagePhaseLineToNeutralMeasurandValue: number | undefined;
- if (voltagePhaseLineToNeutralSampledValueTemplate) {
+ phaseLineToNeutralValue as MeterValuePhase
+ )
+ let voltagePhaseLineToNeutralMeasurandValue: number | undefined
+ if (voltagePhaseLineToNeutralSampledValueTemplate != null) {
const voltagePhaseLineToNeutralSampledValueTemplateValue = isNotEmptyString(
- voltagePhaseLineToNeutralSampledValueTemplate.value,
+ voltagePhaseLineToNeutralSampledValueTemplate.value
)
? parseInt(voltagePhaseLineToNeutralSampledValueTemplate.value)
- : chargingStation.stationInfo.voltageOut!;
+ : // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ chargingStation.stationInfo.voltageOut!
const fluctuationPhaseToNeutralPercent =
voltagePhaseLineToNeutralSampledValueTemplate.fluctuationPercent ??
- Constants.DEFAULT_FLUCTUATION_PERCENT;
+ Constants.DEFAULT_FLUCTUATION_PERCENT
voltagePhaseLineToNeutralMeasurandValue = getRandomFloatFluctuatedRounded(
voltagePhaseLineToNeutralSampledValueTemplateValue,
- fluctuationPhaseToNeutralPercent,
- );
+ fluctuationPhaseToNeutralPercent
+ )
}
meterValue.sampledValue.push(
buildSampledValue(
voltagePhaseLineToNeutralSampledValueTemplate ?? voltageSampledValueTemplate,
voltagePhaseLineToNeutralMeasurandValue ?? voltageMeasurandValue,
undefined,
- phaseLineToNeutralValue as MeterValuePhase,
- ),
- );
- if (chargingStation.stationInfo?.phaseLineToLineVoltageMeterValues) {
+ phaseLineToNeutralValue as MeterValuePhase
+ )
+ )
+ if (chargingStation.stationInfo?.phaseLineToLineVoltageMeterValues === true) {
const phaseLineToLineValue = `L${phase}-L${
(phase + 1) % chargingStation.getNumberOfPhases() !== 0
? (phase + 1) % chargingStation.getNumberOfPhases()
: chargingStation.getNumberOfPhases()
- }`;
+ }`
const voltagePhaseLineToLineValueRounded = roundTo(
Math.sqrt(chargingStation.getNumberOfPhases()) *
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
chargingStation.stationInfo.voltageOut!,
- 2,
- );
+ 2
+ )
const voltagePhaseLineToLineSampledValueTemplate = getSampledValueTemplate(
chargingStation,
connectorId,
MeterValueMeasurand.VOLTAGE,
- phaseLineToLineValue as MeterValuePhase,
- );
- let voltagePhaseLineToLineMeasurandValue: number | undefined;
- if (voltagePhaseLineToLineSampledValueTemplate) {
+ phaseLineToLineValue as MeterValuePhase
+ )
+ let voltagePhaseLineToLineMeasurandValue: number | undefined
+ if (voltagePhaseLineToLineSampledValueTemplate != null) {
const voltagePhaseLineToLineSampledValueTemplateValue = isNotEmptyString(
- voltagePhaseLineToLineSampledValueTemplate.value,
+ voltagePhaseLineToLineSampledValueTemplate.value
)
? parseInt(voltagePhaseLineToLineSampledValueTemplate.value)
- : voltagePhaseLineToLineValueRounded;
+ : voltagePhaseLineToLineValueRounded
const fluctuationPhaseLineToLinePercent =
voltagePhaseLineToLineSampledValueTemplate.fluctuationPercent ??
- Constants.DEFAULT_FLUCTUATION_PERCENT;
+ Constants.DEFAULT_FLUCTUATION_PERCENT
voltagePhaseLineToLineMeasurandValue = getRandomFloatFluctuatedRounded(
voltagePhaseLineToLineSampledValueTemplateValue,
- fluctuationPhaseLineToLinePercent,
- );
+ fluctuationPhaseLineToLinePercent
+ )
}
const defaultVoltagePhaseLineToLineMeasurandValue = getRandomFloatFluctuatedRounded(
voltagePhaseLineToLineValueRounded,
- fluctuationPercent,
- );
+ fluctuationPercent
+ )
meterValue.sampledValue.push(
buildSampledValue(
voltagePhaseLineToLineSampledValueTemplate ?? voltageSampledValueTemplate,
voltagePhaseLineToLineMeasurandValue ?? defaultVoltagePhaseLineToLineMeasurandValue,
undefined,
- phaseLineToLineValue as MeterValuePhase,
- ),
- );
+ phaseLineToLineValue as MeterValuePhase
+ )
+ )
}
}
}
powerSampledValueTemplate = getSampledValueTemplate(
chargingStation,
connectorId,
- MeterValueMeasurand.POWER_ACTIVE_IMPORT,
- );
+ MeterValueMeasurand.POWER_ACTIVE_IMPORT
+ )
if (chargingStation.getNumberOfPhases() === 3) {
powerPerPhaseSampledValueTemplates = {
L1: getSampledValueTemplate(
chargingStation,
connectorId,
MeterValueMeasurand.POWER_ACTIVE_IMPORT,
- MeterValuePhase.L1_N,
+ MeterValuePhase.L1_N
),
L2: getSampledValueTemplate(
chargingStation,
connectorId,
MeterValueMeasurand.POWER_ACTIVE_IMPORT,
- MeterValuePhase.L2_N,
+ MeterValuePhase.L2_N
),
L3: getSampledValueTemplate(
chargingStation,
connectorId,
MeterValueMeasurand.POWER_ACTIVE_IMPORT,
- MeterValuePhase.L3_N,
- ),
- };
+ MeterValuePhase.L3_N
+ )
+ }
}
- if (powerSampledValueTemplate) {
- checkMeasurandPowerDivider(chargingStation, powerSampledValueTemplate.measurand!);
+ if (powerSampledValueTemplate != null) {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ checkMeasurandPowerDivider(chargingStation, powerSampledValueTemplate.measurand!)
const errMsg = `MeterValues measurand ${
powerSampledValueTemplate.measurand ?? MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER
}: Unknown ${chargingStation.stationInfo?.currentOutType} currentOutType in template file ${
chargingStation.templateFile
}, cannot calculate ${
powerSampledValueTemplate.measurand ?? MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER
- } measurand value`;
- const powerMeasurandValues: MeasurandValues = {} as MeasurandValues;
- const unitDivider = powerSampledValueTemplate?.unit === MeterValueUnit.KILO_WATT ? 1000 : 1;
+ } measurand value`
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
+ const powerMeasurandValues: MeasurandValues = {} as MeasurandValues
+ const unitDivider = powerSampledValueTemplate?.unit === MeterValueUnit.KILO_WATT ? 1000 : 1
const connectorMaximumAvailablePower =
- chargingStation.getConnectorMaximumAvailablePower(connectorId);
- const connectorMaximumPower = Math.round(connectorMaximumAvailablePower);
+ chargingStation.getConnectorMaximumAvailablePower(connectorId)
+ const connectorMaximumPower = Math.round(connectorMaximumAvailablePower)
const connectorMaximumPowerPerPhase = Math.round(
- connectorMaximumAvailablePower / chargingStation.getNumberOfPhases(),
- );
- const connectorMinimumPower = Math.round(powerSampledValueTemplate.minimumValue ?? 0);
+ connectorMaximumAvailablePower / chargingStation.getNumberOfPhases()
+ )
+ const connectorMinimumPower = Math.round(powerSampledValueTemplate.minimumValue ?? 0)
const connectorMinimumPowerPerPhase = Math.round(
- connectorMinimumPower / chargingStation.getNumberOfPhases(),
- );
+ connectorMinimumPower / chargingStation.getNumberOfPhases()
+ )
switch (chargingStation.stationInfo?.currentOutType) {
case CurrentType.AC:
if (chargingStation.getNumberOfPhases() === 3) {
const defaultFluctuatedPowerPerPhase = isNotEmptyString(
- powerSampledValueTemplate.value,
+ powerSampledValueTemplate.value
)
? getRandomFloatFluctuatedRounded(
- getLimitFromSampledValueTemplateCustomValue(
- powerSampledValueTemplate.value,
- connectorMaximumPower / unitDivider,
- connectorMinimumPower / unitDivider,
- {
- limitationEnabled:
+ getLimitFromSampledValueTemplateCustomValue(
+ powerSampledValueTemplate.value,
+ connectorMaximumPower / unitDivider,
+ connectorMinimumPower / unitDivider,
+ {
+ limitationEnabled:
chargingStation.stationInfo?.customValueLimitationMeterValues,
- fallbackValue: connectorMinimumPower / unitDivider,
- },
- ) / chargingStation.getNumberOfPhases(),
- powerSampledValueTemplate.fluctuationPercent ??
- Constants.DEFAULT_FLUCTUATION_PERCENT,
- )
- : undefined;
+ fallbackValue: connectorMinimumPower / unitDivider
+ }
+ ) / chargingStation.getNumberOfPhases(),
+ powerSampledValueTemplate.fluctuationPercent ??
+ Constants.DEFAULT_FLUCTUATION_PERCENT
+ )
+ : undefined
const phase1FluctuatedValue = isNotEmptyString(
- powerPerPhaseSampledValueTemplates.L1?.value,
+ powerPerPhaseSampledValueTemplates.L1?.value
)
? getRandomFloatFluctuatedRounded(
- getLimitFromSampledValueTemplateCustomValue(
- powerPerPhaseSampledValueTemplates.L1?.value,
- connectorMaximumPowerPerPhase / unitDivider,
- connectorMinimumPowerPerPhase / unitDivider,
- {
- limitationEnabled:
+ getLimitFromSampledValueTemplateCustomValue(
+ powerPerPhaseSampledValueTemplates.L1?.value,
+ connectorMaximumPowerPerPhase / unitDivider,
+ connectorMinimumPowerPerPhase / unitDivider,
+ {
+ limitationEnabled:
chargingStation.stationInfo?.customValueLimitationMeterValues,
- fallbackValue: connectorMinimumPowerPerPhase / unitDivider,
- },
- ),
- powerPerPhaseSampledValueTemplates.L1?.fluctuationPercent ??
- Constants.DEFAULT_FLUCTUATION_PERCENT,
- )
- : undefined;
+ fallbackValue: connectorMinimumPowerPerPhase / unitDivider
+ }
+ ),
+ powerPerPhaseSampledValueTemplates.L1?.fluctuationPercent ??
+ Constants.DEFAULT_FLUCTUATION_PERCENT
+ )
+ : undefined
const phase2FluctuatedValue = isNotEmptyString(
- powerPerPhaseSampledValueTemplates.L2?.value,
+ powerPerPhaseSampledValueTemplates.L2?.value
)
? getRandomFloatFluctuatedRounded(
- getLimitFromSampledValueTemplateCustomValue(
- powerPerPhaseSampledValueTemplates.L2?.value,
- connectorMaximumPowerPerPhase / unitDivider,
- connectorMinimumPowerPerPhase / unitDivider,
- {
- limitationEnabled:
+ getLimitFromSampledValueTemplateCustomValue(
+ powerPerPhaseSampledValueTemplates.L2?.value,
+ connectorMaximumPowerPerPhase / unitDivider,
+ connectorMinimumPowerPerPhase / unitDivider,
+ {
+ limitationEnabled:
chargingStation.stationInfo?.customValueLimitationMeterValues,
- fallbackValue: connectorMinimumPowerPerPhase / unitDivider,
- },
- ),
- powerPerPhaseSampledValueTemplates.L2?.fluctuationPercent ??
- Constants.DEFAULT_FLUCTUATION_PERCENT,
- )
- : undefined;
+ fallbackValue: connectorMinimumPowerPerPhase / unitDivider
+ }
+ ),
+ powerPerPhaseSampledValueTemplates.L2?.fluctuationPercent ??
+ Constants.DEFAULT_FLUCTUATION_PERCENT
+ )
+ : undefined
const phase3FluctuatedValue = isNotEmptyString(
- powerPerPhaseSampledValueTemplates.L3?.value,
+ powerPerPhaseSampledValueTemplates.L3?.value
)
? getRandomFloatFluctuatedRounded(
- getLimitFromSampledValueTemplateCustomValue(
- powerPerPhaseSampledValueTemplates.L3?.value,
- connectorMaximumPowerPerPhase / unitDivider,
- connectorMinimumPowerPerPhase / unitDivider,
- {
- limitationEnabled:
+ getLimitFromSampledValueTemplateCustomValue(
+ powerPerPhaseSampledValueTemplates.L3?.value,
+ connectorMaximumPowerPerPhase / unitDivider,
+ connectorMinimumPowerPerPhase / unitDivider,
+ {
+ limitationEnabled:
chargingStation.stationInfo?.customValueLimitationMeterValues,
- fallbackValue: connectorMinimumPowerPerPhase / unitDivider,
- },
- ),
- powerPerPhaseSampledValueTemplates.L3?.fluctuationPercent ??
- Constants.DEFAULT_FLUCTUATION_PERCENT,
- )
- : undefined;
+ fallbackValue: connectorMinimumPowerPerPhase / unitDivider
+ }
+ ),
+ powerPerPhaseSampledValueTemplates.L3?.fluctuationPercent ??
+ Constants.DEFAULT_FLUCTUATION_PERCENT
+ )
+ : undefined
powerMeasurandValues.L1 =
phase1FluctuatedValue ??
defaultFluctuatedPowerPerPhase ??
getRandomFloatRounded(
connectorMaximumPowerPerPhase / unitDivider,
- connectorMinimumPowerPerPhase / unitDivider,
- );
+ connectorMinimumPowerPerPhase / unitDivider
+ )
powerMeasurandValues.L2 =
phase2FluctuatedValue ??
defaultFluctuatedPowerPerPhase ??
getRandomFloatRounded(
connectorMaximumPowerPerPhase / unitDivider,
- connectorMinimumPowerPerPhase / unitDivider,
- );
+ connectorMinimumPowerPerPhase / unitDivider
+ )
powerMeasurandValues.L3 =
phase3FluctuatedValue ??
defaultFluctuatedPowerPerPhase ??
getRandomFloatRounded(
connectorMaximumPowerPerPhase / unitDivider,
- connectorMinimumPowerPerPhase / unitDivider,
- );
+ connectorMinimumPowerPerPhase / unitDivider
+ )
} else {
powerMeasurandValues.L1 = isNotEmptyString(powerSampledValueTemplate.value)
? getRandomFloatFluctuatedRounded(
- getLimitFromSampledValueTemplateCustomValue(
- powerSampledValueTemplate.value,
- connectorMaximumPower / unitDivider,
- connectorMinimumPower / unitDivider,
- {
- limitationEnabled:
- chargingStation.stationInfo?.customValueLimitationMeterValues,
- fallbackValue: connectorMinimumPower / unitDivider,
- },
- ),
- powerSampledValueTemplate.fluctuationPercent ??
- Constants.DEFAULT_FLUCTUATION_PERCENT,
- )
- : getRandomFloatRounded(
- connectorMaximumPower / unitDivider,
- connectorMinimumPower / unitDivider,
- );
- powerMeasurandValues.L2 = 0;
- powerMeasurandValues.L3 = 0;
- }
- powerMeasurandValues.allPhases = roundTo(
- powerMeasurandValues.L1 + powerMeasurandValues.L2 + powerMeasurandValues.L3,
- 2,
- );
- break;
- case CurrentType.DC:
- powerMeasurandValues.allPhases = isNotEmptyString(powerSampledValueTemplate.value)
- ? getRandomFloatFluctuatedRounded(
getLimitFromSampledValueTemplateCustomValue(
powerSampledValueTemplate.value,
connectorMaximumPower / unitDivider,
connectorMinimumPower / unitDivider,
{
limitationEnabled:
- chargingStation.stationInfo?.customValueLimitationMeterValues,
- fallbackValue: connectorMinimumPower / unitDivider,
- },
+ chargingStation.stationInfo?.customValueLimitationMeterValues,
+ fallbackValue: connectorMinimumPower / unitDivider
+ }
),
powerSampledValueTemplate.fluctuationPercent ??
- Constants.DEFAULT_FLUCTUATION_PERCENT,
+ Constants.DEFAULT_FLUCTUATION_PERCENT
)
- : getRandomFloatRounded(
+ : getRandomFloatRounded(
+ connectorMaximumPower / unitDivider,
+ connectorMinimumPower / unitDivider
+ )
+ powerMeasurandValues.L2 = 0
+ powerMeasurandValues.L3 = 0
+ }
+ powerMeasurandValues.allPhases = roundTo(
+ powerMeasurandValues.L1 + powerMeasurandValues.L2 + powerMeasurandValues.L3,
+ 2
+ )
+ break
+ case CurrentType.DC:
+ powerMeasurandValues.allPhases = isNotEmptyString(powerSampledValueTemplate.value)
+ ? getRandomFloatFluctuatedRounded(
+ getLimitFromSampledValueTemplateCustomValue(
+ powerSampledValueTemplate.value,
connectorMaximumPower / unitDivider,
connectorMinimumPower / unitDivider,
- );
- break;
+ {
+ limitationEnabled:
+ chargingStation.stationInfo?.customValueLimitationMeterValues,
+ fallbackValue: connectorMinimumPower / unitDivider
+ }
+ ),
+ powerSampledValueTemplate.fluctuationPercent ??
+ Constants.DEFAULT_FLUCTUATION_PERCENT
+ )
+ : getRandomFloatRounded(
+ connectorMaximumPower / unitDivider,
+ connectorMinimumPower / unitDivider
+ )
+ break
default:
- logger.error(`${chargingStation.logPrefix()} ${errMsg}`);
- throw new OCPPError(ErrorType.INTERNAL_ERROR, errMsg, RequestCommand.METER_VALUES);
+ logger.error(`${chargingStation.logPrefix()} ${errMsg}`)
+ throw new OCPPError(ErrorType.INTERNAL_ERROR, errMsg, RequestCommand.METER_VALUES)
}
meterValue.sampledValue.push(
- buildSampledValue(powerSampledValueTemplate, powerMeasurandValues.allPhases),
- );
- const sampledValuesIndex = meterValue.sampledValue.length - 1;
- const connectorMaximumPowerRounded = roundTo(connectorMaximumPower / unitDivider, 2);
- const connectorMinimumPowerRounded = roundTo(connectorMinimumPower / unitDivider, 2);
+ buildSampledValue(powerSampledValueTemplate, powerMeasurandValues.allPhases)
+ )
+ const sampledValuesIndex = meterValue.sampledValue.length - 1
+ const connectorMaximumPowerRounded = roundTo(connectorMaximumPower / unitDivider, 2)
+ const connectorMinimumPowerRounded = roundTo(connectorMinimumPower / unitDivider, 2)
if (
convertToFloat(meterValue.sampledValue[sampledValuesIndex].value) >
connectorMaximumPowerRounded ||
MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER
}: connector id ${connectorId}, transaction id ${connector?.transactionId}, value: ${connectorMinimumPowerRounded}/${
meterValue.sampledValue[sampledValuesIndex].value
- }/${connectorMaximumPowerRounded}`,
- );
+ }/${connectorMaximumPowerRounded}`
+ )
}
for (
let phase = 1;
chargingStation.getNumberOfPhases() === 3 && phase <= chargingStation.getNumberOfPhases();
phase++
) {
- const phaseValue = `L${phase}-N`;
+ const phaseValue = `L${phase}-N`
meterValue.sampledValue.push(
buildSampledValue(
powerPerPhaseSampledValueTemplates[
] ?? powerSampledValueTemplate,
powerMeasurandValues[`L${phase}` as keyof MeasurandPerPhaseSampledValueTemplates],
undefined,
- phaseValue as MeterValuePhase,
- ),
- );
- const sampledValuesPerPhaseIndex = meterValue.sampledValue.length - 1;
+ phaseValue as MeterValuePhase
+ )
+ )
+ const sampledValuesPerPhaseIndex = meterValue.sampledValue.length - 1
const connectorMaximumPowerPerPhaseRounded = roundTo(
connectorMaximumPowerPerPhase / unitDivider,
- 2,
- );
+ 2
+ )
const connectorMinimumPowerPerPhaseRounded = roundTo(
connectorMinimumPowerPerPhase / unitDivider,
- 2,
- );
+ 2
+ )
if (
convertToFloat(meterValue.sampledValue[sampledValuesPerPhaseIndex].value) >
connectorMaximumPowerPerPhaseRounded ||
meterValue.sampledValue[sampledValuesPerPhaseIndex].phase
}, connector id ${connectorId}, transaction id ${connector?.transactionId}, value: ${connectorMinimumPowerPerPhaseRounded}/${
meterValue.sampledValue[sampledValuesPerPhaseIndex].value
- }/${connectorMaximumPowerPerPhaseRounded}`,
- );
+ }/${connectorMaximumPowerPerPhaseRounded}`
+ )
}
}
}
currentSampledValueTemplate = getSampledValueTemplate(
chargingStation,
connectorId,
- MeterValueMeasurand.CURRENT_IMPORT,
- );
+ MeterValueMeasurand.CURRENT_IMPORT
+ )
if (chargingStation.getNumberOfPhases() === 3) {
currentPerPhaseSampledValueTemplates = {
L1: getSampledValueTemplate(
chargingStation,
connectorId,
MeterValueMeasurand.CURRENT_IMPORT,
- MeterValuePhase.L1,
+ MeterValuePhase.L1
),
L2: getSampledValueTemplate(
chargingStation,
connectorId,
MeterValueMeasurand.CURRENT_IMPORT,
- MeterValuePhase.L2,
+ MeterValuePhase.L2
),
L3: getSampledValueTemplate(
chargingStation,
connectorId,
MeterValueMeasurand.CURRENT_IMPORT,
- MeterValuePhase.L3,
- ),
- };
+ MeterValuePhase.L3
+ )
+ }
}
- if (currentSampledValueTemplate) {
- checkMeasurandPowerDivider(chargingStation, currentSampledValueTemplate.measurand!);
+ if (currentSampledValueTemplate != null) {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ checkMeasurandPowerDivider(chargingStation, currentSampledValueTemplate.measurand!)
const errMsg = `MeterValues measurand ${
currentSampledValueTemplate.measurand ?? MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER
}: Unknown ${chargingStation.stationInfo?.currentOutType} currentOutType in template file ${
chargingStation.templateFile
}, cannot calculate ${
currentSampledValueTemplate.measurand ?? MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER
- } measurand value`;
- const currentMeasurandValues: MeasurandValues = {} as MeasurandValues;
+ } measurand value`
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
+ const currentMeasurandValues: MeasurandValues = {} as MeasurandValues
const connectorMaximumAvailablePower =
- chargingStation.getConnectorMaximumAvailablePower(connectorId);
- const connectorMinimumAmperage = currentSampledValueTemplate.minimumValue ?? 0;
- let connectorMaximumAmperage: number;
+ chargingStation.getConnectorMaximumAvailablePower(connectorId)
+ const connectorMinimumAmperage = currentSampledValueTemplate.minimumValue ?? 0
+ let connectorMaximumAmperage: number
switch (chargingStation.stationInfo?.currentOutType) {
case CurrentType.AC:
connectorMaximumAmperage = ACElectricUtils.amperagePerPhaseFromPower(
chargingStation.getNumberOfPhases(),
connectorMaximumAvailablePower,
- chargingStation.stationInfo.voltageOut!,
- );
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ chargingStation.stationInfo.voltageOut!
+ )
if (chargingStation.getNumberOfPhases() === 3) {
const defaultFluctuatedAmperagePerPhase = isNotEmptyString(
- currentSampledValueTemplate.value,
+ currentSampledValueTemplate.value
)
? getRandomFloatFluctuatedRounded(
- getLimitFromSampledValueTemplateCustomValue(
- currentSampledValueTemplate.value,
- connectorMaximumAmperage,
- connectorMinimumAmperage,
- {
- limitationEnabled:
+ getLimitFromSampledValueTemplateCustomValue(
+ currentSampledValueTemplate.value,
+ connectorMaximumAmperage,
+ connectorMinimumAmperage,
+ {
+ limitationEnabled:
chargingStation.stationInfo?.customValueLimitationMeterValues,
- fallbackValue: connectorMinimumAmperage,
- },
- ),
- currentSampledValueTemplate.fluctuationPercent ??
- Constants.DEFAULT_FLUCTUATION_PERCENT,
- )
- : undefined;
+ fallbackValue: connectorMinimumAmperage
+ }
+ ),
+ currentSampledValueTemplate.fluctuationPercent ??
+ Constants.DEFAULT_FLUCTUATION_PERCENT
+ )
+ : undefined
const phase1FluctuatedValue = isNotEmptyString(
- currentPerPhaseSampledValueTemplates.L1?.value,
+ currentPerPhaseSampledValueTemplates.L1?.value
)
? getRandomFloatFluctuatedRounded(
- getLimitFromSampledValueTemplateCustomValue(
- currentPerPhaseSampledValueTemplates.L1?.value,
- connectorMaximumAmperage,
- connectorMinimumAmperage,
- {
- limitationEnabled:
+ getLimitFromSampledValueTemplateCustomValue(
+ currentPerPhaseSampledValueTemplates.L1?.value,
+ connectorMaximumAmperage,
+ connectorMinimumAmperage,
+ {
+ limitationEnabled:
chargingStation.stationInfo?.customValueLimitationMeterValues,
- fallbackValue: connectorMinimumAmperage,
- },
- ),
- currentPerPhaseSampledValueTemplates.L1?.fluctuationPercent ??
- Constants.DEFAULT_FLUCTUATION_PERCENT,
- )
- : undefined;
+ fallbackValue: connectorMinimumAmperage
+ }
+ ),
+ currentPerPhaseSampledValueTemplates.L1?.fluctuationPercent ??
+ Constants.DEFAULT_FLUCTUATION_PERCENT
+ )
+ : undefined
const phase2FluctuatedValue = isNotEmptyString(
- currentPerPhaseSampledValueTemplates.L2?.value,
+ currentPerPhaseSampledValueTemplates.L2?.value
)
? getRandomFloatFluctuatedRounded(
- getLimitFromSampledValueTemplateCustomValue(
- currentPerPhaseSampledValueTemplates.L2?.value,
- connectorMaximumAmperage,
- connectorMinimumAmperage,
- {
- limitationEnabled:
+ getLimitFromSampledValueTemplateCustomValue(
+ currentPerPhaseSampledValueTemplates.L2?.value,
+ connectorMaximumAmperage,
+ connectorMinimumAmperage,
+ {
+ limitationEnabled:
chargingStation.stationInfo?.customValueLimitationMeterValues,
- fallbackValue: connectorMinimumAmperage,
- },
- ),
- currentPerPhaseSampledValueTemplates.L2?.fluctuationPercent ??
- Constants.DEFAULT_FLUCTUATION_PERCENT,
- )
- : undefined;
+ fallbackValue: connectorMinimumAmperage
+ }
+ ),
+ currentPerPhaseSampledValueTemplates.L2?.fluctuationPercent ??
+ Constants.DEFAULT_FLUCTUATION_PERCENT
+ )
+ : undefined
const phase3FluctuatedValue = isNotEmptyString(
- currentPerPhaseSampledValueTemplates.L3?.value,
+ currentPerPhaseSampledValueTemplates.L3?.value
)
? getRandomFloatFluctuatedRounded(
- getLimitFromSampledValueTemplateCustomValue(
- currentPerPhaseSampledValueTemplates.L3?.value,
- connectorMaximumAmperage,
- connectorMinimumAmperage,
- {
- limitationEnabled:
+ getLimitFromSampledValueTemplateCustomValue(
+ currentPerPhaseSampledValueTemplates.L3?.value,
+ connectorMaximumAmperage,
+ connectorMinimumAmperage,
+ {
+ limitationEnabled:
chargingStation.stationInfo?.customValueLimitationMeterValues,
- fallbackValue: connectorMinimumAmperage,
- },
- ),
- currentPerPhaseSampledValueTemplates.L3?.fluctuationPercent ??
- Constants.DEFAULT_FLUCTUATION_PERCENT,
- )
- : undefined;
+ fallbackValue: connectorMinimumAmperage
+ }
+ ),
+ currentPerPhaseSampledValueTemplates.L3?.fluctuationPercent ??
+ Constants.DEFAULT_FLUCTUATION_PERCENT
+ )
+ : undefined
currentMeasurandValues.L1 =
phase1FluctuatedValue ??
defaultFluctuatedAmperagePerPhase ??
- getRandomFloatRounded(connectorMaximumAmperage, connectorMinimumAmperage);
+ getRandomFloatRounded(connectorMaximumAmperage, connectorMinimumAmperage)
currentMeasurandValues.L2 =
phase2FluctuatedValue ??
defaultFluctuatedAmperagePerPhase ??
- getRandomFloatRounded(connectorMaximumAmperage, connectorMinimumAmperage);
+ getRandomFloatRounded(connectorMaximumAmperage, connectorMinimumAmperage)
currentMeasurandValues.L3 =
phase3FluctuatedValue ??
defaultFluctuatedAmperagePerPhase ??
- getRandomFloatRounded(connectorMaximumAmperage, connectorMinimumAmperage);
+ getRandomFloatRounded(connectorMaximumAmperage, connectorMinimumAmperage)
} else {
currentMeasurandValues.L1 = isNotEmptyString(currentSampledValueTemplate.value)
? getRandomFloatFluctuatedRounded(
- getLimitFromSampledValueTemplateCustomValue(
- currentSampledValueTemplate.value,
- connectorMaximumAmperage,
- connectorMinimumAmperage,
- {
- limitationEnabled:
+ getLimitFromSampledValueTemplateCustomValue(
+ currentSampledValueTemplate.value,
+ connectorMaximumAmperage,
+ connectorMinimumAmperage,
+ {
+ limitationEnabled:
chargingStation.stationInfo?.customValueLimitationMeterValues,
- fallbackValue: connectorMinimumAmperage,
- },
- ),
- currentSampledValueTemplate.fluctuationPercent ??
- Constants.DEFAULT_FLUCTUATION_PERCENT,
- )
- : getRandomFloatRounded(connectorMaximumAmperage, connectorMinimumAmperage);
- currentMeasurandValues.L2 = 0;
- currentMeasurandValues.L3 = 0;
+ fallbackValue: connectorMinimumAmperage
+ }
+ ),
+ currentSampledValueTemplate.fluctuationPercent ??
+ Constants.DEFAULT_FLUCTUATION_PERCENT
+ )
+ : getRandomFloatRounded(connectorMaximumAmperage, connectorMinimumAmperage)
+ currentMeasurandValues.L2 = 0
+ currentMeasurandValues.L3 = 0
}
currentMeasurandValues.allPhases = roundTo(
(currentMeasurandValues.L1 + currentMeasurandValues.L2 + currentMeasurandValues.L3) /
chargingStation.getNumberOfPhases(),
- 2,
- );
- break;
+ 2
+ )
+ break
case CurrentType.DC:
connectorMaximumAmperage = DCElectricUtils.amperage(
connectorMaximumAvailablePower,
- chargingStation.stationInfo.voltageOut!,
- );
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ chargingStation.stationInfo.voltageOut!
+ )
currentMeasurandValues.allPhases = isNotEmptyString(currentSampledValueTemplate.value)
? getRandomFloatFluctuatedRounded(
- getLimitFromSampledValueTemplateCustomValue(
- currentSampledValueTemplate.value,
- connectorMaximumAmperage,
- connectorMinimumAmperage,
- {
- limitationEnabled:
+ getLimitFromSampledValueTemplateCustomValue(
+ currentSampledValueTemplate.value,
+ connectorMaximumAmperage,
+ connectorMinimumAmperage,
+ {
+ limitationEnabled:
chargingStation.stationInfo?.customValueLimitationMeterValues,
- fallbackValue: connectorMinimumAmperage,
- },
- ),
- currentSampledValueTemplate.fluctuationPercent ??
- Constants.DEFAULT_FLUCTUATION_PERCENT,
- )
- : getRandomFloatRounded(connectorMaximumAmperage, connectorMinimumAmperage);
- break;
+ fallbackValue: connectorMinimumAmperage
+ }
+ ),
+ currentSampledValueTemplate.fluctuationPercent ??
+ Constants.DEFAULT_FLUCTUATION_PERCENT
+ )
+ : getRandomFloatRounded(connectorMaximumAmperage, connectorMinimumAmperage)
+ break
default:
- logger.error(`${chargingStation.logPrefix()} ${errMsg}`);
- throw new OCPPError(ErrorType.INTERNAL_ERROR, errMsg, RequestCommand.METER_VALUES);
+ logger.error(`${chargingStation.logPrefix()} ${errMsg}`)
+ throw new OCPPError(ErrorType.INTERNAL_ERROR, errMsg, RequestCommand.METER_VALUES)
}
meterValue.sampledValue.push(
- buildSampledValue(currentSampledValueTemplate, currentMeasurandValues.allPhases),
- );
- const sampledValuesIndex = meterValue.sampledValue.length - 1;
+ buildSampledValue(currentSampledValueTemplate, currentMeasurandValues.allPhases)
+ )
+ const sampledValuesIndex = meterValue.sampledValue.length - 1
if (
convertToFloat(meterValue.sampledValue[sampledValuesIndex].value) >
connectorMaximumAmperage ||
MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER
}: connector id ${connectorId}, transaction id ${connector?.transactionId}, value: ${connectorMinimumAmperage}/${
meterValue.sampledValue[sampledValuesIndex].value
- }/${connectorMaximumAmperage}`,
- );
+ }/${connectorMaximumAmperage}`
+ )
}
for (
let phase = 1;
chargingStation.getNumberOfPhases() === 3 && phase <= chargingStation.getNumberOfPhases();
phase++
) {
- const phaseValue = `L${phase}`;
+ const phaseValue = `L${phase}`
meterValue.sampledValue.push(
buildSampledValue(
currentPerPhaseSampledValueTemplates[
] ?? currentSampledValueTemplate,
currentMeasurandValues[phaseValue as keyof MeasurandPerPhaseSampledValueTemplates],
undefined,
- phaseValue as MeterValuePhase,
- ),
- );
- const sampledValuesPerPhaseIndex = meterValue.sampledValue.length - 1;
+ phaseValue as MeterValuePhase
+ )
+ )
+ const sampledValuesPerPhaseIndex = meterValue.sampledValue.length - 1
if (
convertToFloat(meterValue.sampledValue[sampledValuesPerPhaseIndex].value) >
connectorMaximumAmperage ||
meterValue.sampledValue[sampledValuesPerPhaseIndex].phase
}, connector id ${connectorId}, transaction id ${connector?.transactionId}, value: ${connectorMinimumAmperage}/${
meterValue.sampledValue[sampledValuesPerPhaseIndex].value
- }/${connectorMaximumAmperage}`,
- );
+ }/${connectorMaximumAmperage}`
+ )
}
}
}
// Energy.Active.Import.Register measurand (default)
- energySampledValueTemplate = getSampledValueTemplate(chargingStation, connectorId);
- if (energySampledValueTemplate) {
- checkMeasurandPowerDivider(chargingStation, energySampledValueTemplate.measurand!);
+ energySampledValueTemplate = getSampledValueTemplate(chargingStation, connectorId)
+ if (energySampledValueTemplate != null) {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ checkMeasurandPowerDivider(chargingStation, energySampledValueTemplate.measurand!)
const unitDivider =
- energySampledValueTemplate?.unit === MeterValueUnit.KILO_WATT_HOUR ? 1000 : 1;
+ energySampledValueTemplate?.unit === MeterValueUnit.KILO_WATT_HOUR ? 1000 : 1
const connectorMaximumAvailablePower =
- chargingStation.getConnectorMaximumAvailablePower(connectorId);
+ chargingStation.getConnectorMaximumAvailablePower(connectorId)
const connectorMaximumEnergyRounded = roundTo(
(connectorMaximumAvailablePower * interval) / (3600 * 1000),
- 2,
- );
+ 2
+ )
const connectorMinimumEnergyRounded = roundTo(
energySampledValueTemplate.minimumValue ?? 0,
- 2,
- );
+ 2
+ )
const energyValueRounded = isNotEmptyString(energySampledValueTemplate.value)
? getRandomFloatFluctuatedRounded(
- getLimitFromSampledValueTemplateCustomValue(
- energySampledValueTemplate.value,
- connectorMaximumEnergyRounded,
- connectorMinimumEnergyRounded,
- {
- limitationEnabled: chargingStation.stationInfo?.customValueLimitationMeterValues,
- fallbackValue: connectorMinimumEnergyRounded,
- unitMultiplier: unitDivider,
- },
- ),
- energySampledValueTemplate.fluctuationPercent ??
- Constants.DEFAULT_FLUCTUATION_PERCENT,
- )
- : getRandomFloatRounded(connectorMaximumEnergyRounded, connectorMinimumEnergyRounded);
+ getLimitFromSampledValueTemplateCustomValue(
+ energySampledValueTemplate.value,
+ connectorMaximumEnergyRounded,
+ connectorMinimumEnergyRounded,
+ {
+ limitationEnabled: chargingStation.stationInfo?.customValueLimitationMeterValues,
+ fallbackValue: connectorMinimumEnergyRounded,
+ unitMultiplier: unitDivider
+ }
+ ),
+ energySampledValueTemplate.fluctuationPercent ?? Constants.DEFAULT_FLUCTUATION_PERCENT
+ )
+ : getRandomFloatRounded(connectorMaximumEnergyRounded, connectorMinimumEnergyRounded)
// Persist previous value on connector
- if (connector) {
+ if (connector != null) {
if (
- isNullOrUndefined(connector.energyActiveImportRegisterValue) === false &&
+ !isNullOrUndefined(connector.energyActiveImportRegisterValue) &&
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
connector.energyActiveImportRegisterValue! >= 0 &&
- isNullOrUndefined(connector.transactionEnergyActiveImportRegisterValue) === false &&
+ !isNullOrUndefined(connector.transactionEnergyActiveImportRegisterValue) &&
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
connector.transactionEnergyActiveImportRegisterValue! >= 0
) {
- connector.energyActiveImportRegisterValue! += energyValueRounded;
- connector.transactionEnergyActiveImportRegisterValue! += energyValueRounded;
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ connector.energyActiveImportRegisterValue! += energyValueRounded
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ connector.transactionEnergyActiveImportRegisterValue! += energyValueRounded
} else {
- connector.energyActiveImportRegisterValue = 0;
- connector.transactionEnergyActiveImportRegisterValue = 0;
+ connector.energyActiveImportRegisterValue = 0
+ connector.transactionEnergyActiveImportRegisterValue = 0
}
}
meterValue.sampledValue.push(
roundTo(
chargingStation.getEnergyActiveImportRegisterByTransactionId(transactionId) /
unitDivider,
- 2,
- ),
- ),
- );
- const sampledValuesIndex = meterValue.sampledValue.length - 1;
+ 2
+ )
+ )
+ )
+ const sampledValuesIndex = meterValue.sampledValue.length - 1
if (
energyValueRounded > connectorMaximumEnergyRounded ||
energyValueRounded < connectorMinimumEnergyRounded ||
`${chargingStation.logPrefix()} MeterValues measurand ${
meterValue.sampledValue[sampledValuesIndex].measurand ??
MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER
- }: connector id ${connectorId}, transaction id ${connector?.transactionId}, value: ${connectorMinimumEnergyRounded}/${energyValueRounded}/${connectorMaximumEnergyRounded}, duration: ${interval}ms`,
- );
+ }: connector id ${connectorId}, transaction id ${connector?.transactionId}, value: ${connectorMinimumEnergyRounded}/${energyValueRounded}/${connectorMaximumEnergyRounded}, duration: ${interval}ms`
+ )
}
}
- return meterValue;
+ return meterValue
case OCPPVersion.VERSION_20:
case OCPPVersion.VERSION_201:
default:
throw new BaseError(
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
- `Cannot build meterValue: OCPP version ${chargingStation.stationInfo?.ocppVersion} not supported`,
- );
+ `Cannot build meterValue: OCPP version ${chargingStation.stationInfo?.ocppVersion} not supported`
+ )
}
-};
+}
export const buildTransactionEndMeterValue = (
chargingStation: ChargingStation,
connectorId: number,
- meterStop: number,
+ meterStop: number
): MeterValue => {
- let meterValue: MeterValue;
- let sampledValueTemplate: SampledValueTemplate | undefined;
- let unitDivider: number;
+ let meterValue: MeterValue
+ let sampledValueTemplate: SampledValueTemplate | undefined
+ let unitDivider: number
switch (chargingStation.stationInfo?.ocppVersion) {
case OCPPVersion.VERSION_16:
meterValue = {
timestamp: new Date(),
- sampledValue: [],
- };
+ sampledValue: []
+ }
// Energy.Active.Import.Register measurand (default)
- sampledValueTemplate = getSampledValueTemplate(chargingStation, connectorId);
- unitDivider = sampledValueTemplate?.unit === MeterValueUnit.KILO_WATT_HOUR ? 1000 : 1;
+ sampledValueTemplate = getSampledValueTemplate(chargingStation, connectorId)
+ unitDivider = sampledValueTemplate?.unit === MeterValueUnit.KILO_WATT_HOUR ? 1000 : 1
meterValue.sampledValue.push(
buildSampledValue(
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
sampledValueTemplate!,
roundTo((meterStop ?? 0) / unitDivider, 4),
- MeterValueContext.TRANSACTION_END,
- ),
- );
- return meterValue;
+ MeterValueContext.TRANSACTION_END
+ )
+ )
+ return meterValue
case OCPPVersion.VERSION_20:
case OCPPVersion.VERSION_201:
default:
throw new BaseError(
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
- `Cannot build meterValue: OCPP version ${chargingStation.stationInfo?.ocppVersion} not supported`,
- );
+ `Cannot build meterValue: OCPP version ${chargingStation.stationInfo?.ocppVersion} not supported`
+ )
}
-};
+}
const checkMeasurandPowerDivider = (
chargingStation: ChargingStation,
- measurandType: MeterValueMeasurand,
+ measurandType: MeterValueMeasurand
): void => {
if (isUndefined(chargingStation.powerDivider)) {
const errMsg = `MeterValues measurand ${
measurandType ?? MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER
- }: powerDivider is undefined`;
- logger.error(`${chargingStation.logPrefix()} ${errMsg}`);
- throw new OCPPError(ErrorType.INTERNAL_ERROR, errMsg, RequestCommand.METER_VALUES);
+ }: powerDivider is undefined`
+ logger.error(`${chargingStation.logPrefix()} ${errMsg}`)
+ throw new OCPPError(ErrorType.INTERNAL_ERROR, errMsg, RequestCommand.METER_VALUES)
} else if (chargingStation?.powerDivider <= 0) {
const errMsg = `MeterValues measurand ${
measurandType ?? MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER
- }: powerDivider have zero or below value ${chargingStation.powerDivider}`;
- logger.error(`${chargingStation.logPrefix()} ${errMsg}`);
- throw new OCPPError(ErrorType.INTERNAL_ERROR, errMsg, RequestCommand.METER_VALUES);
+ }: powerDivider have zero or below value ${chargingStation.powerDivider}`
+ logger.error(`${chargingStation.logPrefix()} ${errMsg}`)
+ throw new OCPPError(ErrorType.INTERNAL_ERROR, errMsg, RequestCommand.METER_VALUES)
}
-};
+}
const getLimitFromSampledValueTemplateCustomValue = (
value: string | undefined,
maxLimit: number,
minLimit: number,
- options?: { limitationEnabled?: boolean; fallbackValue?: number; unitMultiplier?: number },
+ options?: { limitationEnabled?: boolean, fallbackValue?: number, unitMultiplier?: number }
): number => {
options = {
...{
limitationEnabled: false,
unitMultiplier: 1,
- fallbackValue: 0,
+ fallbackValue: 0
},
- ...options,
- };
- const parsedValue = parseInt(value ?? '');
- if (options?.limitationEnabled) {
+ ...options
+ }
+ const parsedValue = parseInt(value ?? '')
+ if (options?.limitationEnabled === true) {
return max(
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
min((!isNaN(parsedValue) ? parsedValue : Infinity) * options.unitMultiplier!, maxLimit),
- minLimit,
- );
+ minLimit
+ )
}
- return (!isNaN(parsedValue) ? parsedValue : options.fallbackValue!) * options.unitMultiplier!;
-};
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ return (!isNaN(parsedValue) ? parsedValue : options.fallbackValue!) * options.unitMultiplier!
+}
const getSampledValueTemplate = (
chargingStation: ChargingStation,
connectorId: number,
measurand: MeterValueMeasurand = MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER,
- phase?: MeterValuePhase,
+ phase?: MeterValuePhase
): SampledValueTemplate | undefined => {
- const onPhaseStr = phase ? `on phase ${phase} ` : '';
- if (OCPPConstants.OCPP_MEASURANDS_SUPPORTED.includes(measurand) === false) {
+ const onPhaseStr = phase != null ? `on phase ${phase} ` : ''
+ if (!OCPPConstants.OCPP_MEASURANDS_SUPPORTED.includes(measurand)) {
logger.warn(
- `${chargingStation.logPrefix()} Trying to get unsupported MeterValues measurand '${measurand}' ${onPhaseStr}in template on connector id ${connectorId}`,
- );
- return;
+ `${chargingStation.logPrefix()} Trying to get unsupported MeterValues measurand '${measurand}' ${onPhaseStr}in template on connector id ${connectorId}`
+ )
+ return
}
if (
measurand !== MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER &&
getConfigurationKey(
chargingStation,
- StandardParametersKey.MeterValuesSampledData,
+ StandardParametersKey.MeterValuesSampledData
)?.value?.includes(measurand) === false
) {
logger.debug(
`${chargingStation.logPrefix()} Trying to get MeterValues measurand '${measurand}' ${onPhaseStr}in template on connector id ${connectorId} not found in '${
StandardParametersKey.MeterValuesSampledData
- }' OCPP parameter`,
- );
- return;
+ }' OCPP parameter`
+ )
+ return
}
const sampledValueTemplates: SampledValueTemplate[] =
- chargingStation.getConnectorStatus(connectorId)!.MeterValues;
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ chargingStation.getConnectorStatus(connectorId)!.MeterValues
for (
let index = 0;
- isNotEmptyArray(sampledValueTemplates) === true && index < sampledValueTemplates.length;
+ isNotEmptyArray(sampledValueTemplates) && index < sampledValueTemplates.length;
index++
) {
if (
- OCPPConstants.OCPP_MEASURANDS_SUPPORTED.includes(
- sampledValueTemplates[index]?.measurand ??
- MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER,
- ) === false
+ !OCPPConstants.OCPP_MEASURANDS_SUPPORTED.includes(
+ sampledValueTemplates[index]?.measurand ?? MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER
+ )
) {
logger.warn(
- `${chargingStation.logPrefix()} Unsupported MeterValues measurand '${measurand}' ${onPhaseStr}in template on connector id ${connectorId}`,
- );
+ `${chargingStation.logPrefix()} Unsupported MeterValues measurand '${measurand}' ${onPhaseStr}in template on connector id ${connectorId}`
+ )
} else if (
- phase &&
+ phase != null &&
sampledValueTemplates[index]?.phase === phase &&
sampledValueTemplates[index]?.measurand === measurand &&
getConfigurationKey(
chargingStation,
- StandardParametersKey.MeterValuesSampledData,
+ StandardParametersKey.MeterValuesSampledData
)?.value?.includes(measurand) === true
) {
- return sampledValueTemplates[index];
+ return sampledValueTemplates[index]
} else if (
- !phase &&
- !sampledValueTemplates[index]?.phase &&
+ phase == null &&
+ sampledValueTemplates[index]?.phase == null &&
sampledValueTemplates[index]?.measurand === measurand &&
getConfigurationKey(
chargingStation,
- StandardParametersKey.MeterValuesSampledData,
+ StandardParametersKey.MeterValuesSampledData
)?.value?.includes(measurand) === true
) {
- return sampledValueTemplates[index];
+ return sampledValueTemplates[index]
} else if (
measurand === MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER &&
- (!sampledValueTemplates[index]?.measurand ||
+ (sampledValueTemplates[index]?.measurand == null ||
sampledValueTemplates[index]?.measurand === measurand)
) {
- return sampledValueTemplates[index];
+ return sampledValueTemplates[index]
}
}
if (measurand === MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER) {
- const errorMsg = `Missing MeterValues for default measurand '${measurand}' in template on connector id ${connectorId}`;
- logger.error(`${chargingStation.logPrefix()} ${errorMsg}`);
- throw new BaseError(errorMsg);
+ const errorMsg = `Missing MeterValues for default measurand '${measurand}' in template on connector id ${connectorId}`
+ logger.error(`${chargingStation.logPrefix()} ${errorMsg}`)
+ throw new BaseError(errorMsg)
}
logger.debug(
- `${chargingStation.logPrefix()} No MeterValues for measurand '${measurand}' ${onPhaseStr}in template on connector id ${connectorId}`,
- );
-};
+ `${chargingStation.logPrefix()} No MeterValues for measurand '${measurand}' ${onPhaseStr}in template on connector id ${connectorId}`
+ )
+}
const buildSampledValue = (
sampledValueTemplate: SampledValueTemplate,
value: number,
context?: MeterValueContext,
- phase?: MeterValuePhase,
+ phase?: MeterValuePhase
): SampledValue => {
- const sampledValueContext = context ?? sampledValueTemplate?.context;
+ const sampledValueContext = context ?? sampledValueTemplate?.context
const sampledValueLocation =
- sampledValueTemplate?.location ?? getMeasurandDefaultLocation(sampledValueTemplate.measurand!);
- const sampledValuePhase = phase ?? sampledValueTemplate?.phase;
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ sampledValueTemplate?.location ?? getMeasurandDefaultLocation(sampledValueTemplate.measurand!)
+ const sampledValuePhase = phase ?? sampledValueTemplate?.phase
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
return {
...(!isNullOrUndefined(sampledValueTemplate.unit) && {
- unit: sampledValueTemplate.unit,
+ unit: sampledValueTemplate.unit
}),
...(!isNullOrUndefined(sampledValueContext) && { context: sampledValueContext }),
...(!isNullOrUndefined(sampledValueTemplate.measurand) && {
- measurand: sampledValueTemplate.measurand,
+ measurand: sampledValueTemplate.measurand
}),
...(!isNullOrUndefined(sampledValueLocation) && { location: sampledValueLocation }),
...(!isNullOrUndefined(value) && { value: value.toString() }),
- ...(!isNullOrUndefined(sampledValuePhase) && { phase: sampledValuePhase }),
- } as SampledValue;
-};
+ ...(!isNullOrUndefined(sampledValuePhase) && { phase: sampledValuePhase })
+ } as SampledValue
+}
const getMeasurandDefaultLocation = (
- measurandType: MeterValueMeasurand,
+ measurandType: MeterValueMeasurand
): MeterValueLocation | undefined => {
switch (measurandType) {
case MeterValueMeasurand.STATE_OF_CHARGE:
- return MeterValueLocation.EV;
+ return MeterValueLocation.EV
}
-};
+}
// const getMeasurandDefaultUnit = (
-// measurandType: MeterValueMeasurand,
+// measurandType: MeterValueMeasurand
// ): MeterValueUnit | undefined => {
// switch (measurandType) {
// case MeterValueMeasurand.CURRENT_EXPORT:
// case MeterValueMeasurand.CURRENT_IMPORT:
// case MeterValueMeasurand.CURRENT_OFFERED:
-// return MeterValueUnit.AMP;
+// return MeterValueUnit.AMP
// case MeterValueMeasurand.ENERGY_ACTIVE_EXPORT_REGISTER:
// case MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER:
-// return MeterValueUnit.WATT_HOUR;
+// return MeterValueUnit.WATT_HOUR
// case MeterValueMeasurand.POWER_ACTIVE_EXPORT:
// case MeterValueMeasurand.POWER_ACTIVE_IMPORT:
// case MeterValueMeasurand.POWER_OFFERED:
-// return MeterValueUnit.WATT;
+// return MeterValueUnit.WATT
// case MeterValueMeasurand.STATE_OF_CHARGE:
-// return MeterValueUnit.PERCENT;
+// return MeterValueUnit.PERCENT
// case MeterValueMeasurand.VOLTAGE:
-// return MeterValueUnit.VOLT;
+// return MeterValueUnit.VOLT
// }
-// };
+// }
+// eslint-disable-next-line @typescript-eslint/no-extraneous-class
export class OCPPServiceUtils {
- public static getMessageTypeString = getMessageTypeString;
- public static sendAndSetConnectorStatus = sendAndSetConnectorStatus;
- public static isIdTagAuthorized = isIdTagAuthorized;
- public static buildTransactionEndMeterValue = buildTransactionEndMeterValue;
- protected static getSampledValueTemplate = getSampledValueTemplate;
- protected static buildSampledValue = buildSampledValue;
+ public static getMessageTypeString = getMessageTypeString
+ public static sendAndSetConnectorStatus = sendAndSetConnectorStatus
+ public static isIdTagAuthorized = isIdTagAuthorized
+ public static buildTransactionEndMeterValue = buildTransactionEndMeterValue
+ protected static getSampledValueTemplate = getSampledValueTemplate
+ protected static buildSampledValue = buildSampledValue
- protected constructor() {
+ protected constructor () {
// This is intentional
}
- public static ajvErrorsToErrorType(errors: ErrorObject[] | null | undefined): ErrorType {
- if (isNotEmptyArray(errors) === true) {
+ public static ajvErrorsToErrorType (errors: ErrorObject[] | null | undefined): ErrorType {
+ if (isNotEmptyArray(errors)) {
for (const error of errors as DefinedError[]) {
switch (error.keyword) {
case 'type':
- return ErrorType.TYPE_CONSTRAINT_VIOLATION;
+ return ErrorType.TYPE_CONSTRAINT_VIOLATION
case 'dependencies':
case 'required':
- return ErrorType.OCCURRENCE_CONSTRAINT_VIOLATION;
+ return ErrorType.OCCURRENCE_CONSTRAINT_VIOLATION
case 'pattern':
case 'format':
- return ErrorType.PROPERTY_CONSTRAINT_VIOLATION;
+ return ErrorType.PROPERTY_CONSTRAINT_VIOLATION
}
}
}
- return ErrorType.FORMAT_VIOLATION;
+ return ErrorType.FORMAT_VIOLATION
}
- public static isRequestCommandSupported(
+ public static isRequestCommandSupported (
chargingStation: ChargingStation,
- command: RequestCommand,
+ command: RequestCommand
): boolean {
- const isRequestCommand = Object.values<RequestCommand>(RequestCommand).includes(command);
+ const isRequestCommand = Object.values<RequestCommand>(RequestCommand).includes(command)
if (
- isRequestCommand === true &&
- !chargingStation.stationInfo?.commandsSupport?.outgoingCommands
+ isRequestCommand &&
+ chargingStation.stationInfo?.commandsSupport?.outgoingCommands == null
) {
- return true;
+ return true
} else if (
- isRequestCommand === true &&
- chargingStation.stationInfo?.commandsSupport?.outgoingCommands?.[command]
+ isRequestCommand &&
+ chargingStation.stationInfo?.commandsSupport?.outgoingCommands?.[command] != null
) {
- return chargingStation.stationInfo?.commandsSupport?.outgoingCommands[command];
+ return chargingStation.stationInfo?.commandsSupport?.outgoingCommands[command]
}
- logger.error(`${chargingStation.logPrefix()} Unknown outgoing OCPP command '${command}'`);
- return false;
+ logger.error(`${chargingStation.logPrefix()} Unknown outgoing OCPP command '${command}'`)
+ return false
}
- public static isIncomingRequestCommandSupported(
+ public static isIncomingRequestCommandSupported (
chargingStation: ChargingStation,
- command: IncomingRequestCommand,
+ command: IncomingRequestCommand
): boolean {
const isIncomingRequestCommand =
- Object.values<IncomingRequestCommand>(IncomingRequestCommand).includes(command);
+ Object.values<IncomingRequestCommand>(IncomingRequestCommand).includes(command)
if (
- isIncomingRequestCommand === true &&
- !chargingStation.stationInfo?.commandsSupport?.incomingCommands
+ isIncomingRequestCommand &&
+ chargingStation.stationInfo?.commandsSupport?.incomingCommands == null
) {
- return true;
+ return true
} else if (
- isIncomingRequestCommand === true &&
- chargingStation.stationInfo?.commandsSupport?.incomingCommands?.[command]
+ isIncomingRequestCommand &&
+ chargingStation.stationInfo?.commandsSupport?.incomingCommands?.[command] != null
) {
- return chargingStation.stationInfo?.commandsSupport?.incomingCommands[command];
+ return chargingStation.stationInfo?.commandsSupport?.incomingCommands[command]
}
- logger.error(`${chargingStation.logPrefix()} Unknown incoming OCPP command '${command}'`);
- return false;
+ logger.error(`${chargingStation.logPrefix()} Unknown incoming OCPP command '${command}'`)
+ return false
}
- public static isMessageTriggerSupported(
+ public static isMessageTriggerSupported (
chargingStation: ChargingStation,
- messageTrigger: MessageTrigger,
+ messageTrigger: MessageTrigger
): boolean {
- const isMessageTrigger = Object.values(MessageTrigger).includes(messageTrigger);
- if (isMessageTrigger === true && !chargingStation.stationInfo?.messageTriggerSupport) {
- return true;
+ const isMessageTrigger = Object.values(MessageTrigger).includes(messageTrigger)
+ if (isMessageTrigger && chargingStation.stationInfo?.messageTriggerSupport == null) {
+ return true
} else if (
- isMessageTrigger === true &&
- chargingStation.stationInfo?.messageTriggerSupport?.[messageTrigger]
+ isMessageTrigger &&
+ chargingStation.stationInfo?.messageTriggerSupport?.[messageTrigger] != null
) {
- return chargingStation.stationInfo?.messageTriggerSupport[messageTrigger];
+ return chargingStation.stationInfo?.messageTriggerSupport[messageTrigger]
}
logger.error(
- `${chargingStation.logPrefix()} Unknown incoming OCPP message trigger '${messageTrigger}'`,
- );
- return false;
+ `${chargingStation.logPrefix()} Unknown incoming OCPP message trigger '${messageTrigger}'`
+ )
+ return false
}
- public static isConnectorIdValid(
+ public static isConnectorIdValid (
chargingStation: ChargingStation,
ocppCommand: IncomingRequestCommand,
- connectorId: number,
+ connectorId: number
): boolean {
if (connectorId < 0) {
logger.error(
- `${chargingStation.logPrefix()} ${ocppCommand} incoming request received with invalid connector id ${connectorId}`,
- );
- return false;
+ `${chargingStation.logPrefix()} ${ocppCommand} incoming request received with invalid connector id ${connectorId}`
+ )
+ return false
}
- return true;
+ return true
}
public static convertDateToISOString<T extends JsonType>(obj: T): void {
for (const key in obj) {
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion, @typescript-eslint/no-non-null-assertion
if (isDate(obj![key])) {
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
- (obj![key] as string) = (obj![key] as Date).toISOString();
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion, @typescript-eslint/no-non-null-assertion
+ (obj![key] as string) = (obj![key] as Date).toISOString()
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion, @typescript-eslint/no-non-null-assertion
} else if (obj![key] !== null && typeof obj![key] === 'object') {
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
- OCPPServiceUtils.convertDateToISOString<T>(obj![key] as T);
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion, @typescript-eslint/no-non-null-assertion
+ OCPPServiceUtils.convertDateToISOString<T>(obj![key] as T)
}
}
}
- public static startHeartbeatInterval(chargingStation: ChargingStation, interval: number): void {
+ public static startHeartbeatInterval (chargingStation: ChargingStation, interval: number): void {
if (chargingStation.heartbeatSetInterval === undefined) {
- chargingStation.startHeartbeat();
+ chargingStation.startHeartbeat()
} else if (chargingStation.getHeartbeatInterval() !== interval) {
- chargingStation.restartHeartbeat();
+ chargingStation.restartHeartbeat()
}
}
relativePath: string,
ocppVersion: OCPPVersion,
moduleName?: string,
- methodName?: string,
+ methodName?: string
): JSONSchemaType<T> {
- const filePath = join(dirname(fileURLToPath(import.meta.url)), relativePath);
+ const filePath = join(dirname(fileURLToPath(import.meta.url)), relativePath)
try {
- return JSON.parse(readFileSync(filePath, 'utf8')) as JSONSchemaType<T>;
+ return JSON.parse(readFileSync(filePath, 'utf8')) as JSONSchemaType<T>
} catch (error) {
handleFileException(
filePath,
FileType.JsonSchema,
error as NodeJS.ErrnoException,
OCPPServiceUtils.logPrefix(ocppVersion, moduleName, methodName),
- { throwError: false },
- );
- return {} as JSONSchemaType<T>;
+ { throwError: false }
+ )
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
+ return {} as JSONSchemaType<T>
}
}
- private static logPrefix = (
+ private static readonly logPrefix = (
ocppVersion: OCPPVersion,
moduleName?: string,
- methodName?: string,
+ methodName?: string
): string => {
const logMsg =
isNotEmptyString(moduleName) && isNotEmptyString(methodName)
? ` OCPP ${ocppVersion} | ${moduleName}.${methodName}:`
- : ` OCPP ${ocppVersion} |`;
- return logPrefix(logMsg);
- };
+ : ` OCPP ${ocppVersion} |`
+ return logPrefix(logMsg)
+ }
}
-export { OCPP16IncomingRequestService } from './1.6/OCPP16IncomingRequestService.js';
-export { OCPP16RequestService } from './1.6/OCPP16RequestService.js';
-export { OCPP16ResponseService } from './1.6/OCPP16ResponseService.js';
-export { OCPP20IncomingRequestService } from './2.0/OCPP20IncomingRequestService.js';
-export { OCPP20RequestService } from './2.0/OCPP20RequestService.js';
-export { OCPP20ResponseService } from './2.0/OCPP20ResponseService.js';
-export { OCPPIncomingRequestService } from './OCPPIncomingRequestService.js';
-export { OCPPRequestService } from './OCPPRequestService.js';
+export { OCPP16IncomingRequestService } from './1.6/OCPP16IncomingRequestService.js'
+export { OCPP16RequestService } from './1.6/OCPP16RequestService.js'
+export { OCPP16ResponseService } from './1.6/OCPP16ResponseService.js'
+export { OCPP20IncomingRequestService } from './2.0/OCPP20IncomingRequestService.js'
+export { OCPP20RequestService } from './2.0/OCPP20RequestService.js'
+export { OCPP20ResponseService } from './2.0/OCPP20ResponseService.js'
+export { OCPPIncomingRequestService } from './OCPPIncomingRequestService.js'
+export { OCPPRequestService } from './OCPPRequestService.js'
export {
buildMeterValue,
buildStatusNotificationRequest,
buildTransactionEndMeterValue,
getMessageTypeString,
isIdTagAuthorized,
- sendAndSetConnectorStatus,
-} from './OCPPServiceUtils.js';
+ sendAndSetConnectorStatus
+} from './OCPPServiceUtils.js'
-import { type IncomingMessage, Server, type ServerResponse } from 'node:http';
-import { type Http2Server, createServer } from 'node:http2';
+import { type IncomingMessage, Server, type ServerResponse } from 'node:http'
+import { type Http2Server, createServer } from 'node:http2'
-import type { WebSocket } from 'ws';
+import type { WebSocket } from 'ws'
-import type { AbstractUIService } from './ui-services/AbstractUIService.js';
-import { UIServiceFactory } from './ui-services/UIServiceFactory.js';
-import { BaseError } from '../../exception/index.js';
+import type { AbstractUIService } from './ui-services/AbstractUIService.js'
+import { UIServiceFactory } from './ui-services/UIServiceFactory.js'
+import { BaseError } from '../../exception/index.js'
import {
ApplicationProtocolVersion,
AuthenticationType,
ProtocolVersion,
type RequestPayload,
type ResponsePayload,
- type UIServerConfiguration,
-} from '../../types/index.js';
+ type UIServerConfiguration
+} from '../../types/index.js'
export abstract class AbstractUIServer {
- public readonly chargingStations: Map<string, ChargingStationData>;
- protected readonly httpServer: Server | Http2Server;
- protected readonly responseHandlers: Map<string, ServerResponse | WebSocket>;
- protected readonly uiServices: Map<ProtocolVersion, AbstractUIService>;
+ public readonly chargingStations: Map<string, ChargingStationData>
+ protected readonly httpServer: Server | Http2Server
+ protected readonly responseHandlers: Map<string, ServerResponse | WebSocket>
+ protected readonly uiServices: Map<ProtocolVersion, AbstractUIService>
- public constructor(protected readonly uiServerConfiguration: UIServerConfiguration) {
- this.chargingStations = new Map<string, ChargingStationData>();
+ public constructor (protected readonly uiServerConfiguration: UIServerConfiguration) {
+ this.chargingStations = new Map<string, ChargingStationData>()
switch (this.uiServerConfiguration.version) {
case ApplicationProtocolVersion.VERSION_11:
- this.httpServer = new Server();
- break;
+ this.httpServer = new Server()
+ break
case ApplicationProtocolVersion.VERSION_20:
- this.httpServer = createServer();
- break;
+ this.httpServer = createServer()
+ break
default:
throw new BaseError(
- `Unsupported application protocol version ${this.uiServerConfiguration.version}`,
- );
+ `Unsupported application protocol version ${this.uiServerConfiguration.version}`
+ )
}
- this.responseHandlers = new Map<string, ServerResponse | WebSocket>();
- this.uiServices = new Map<ProtocolVersion, AbstractUIService>();
+ this.responseHandlers = new Map<string, ServerResponse | WebSocket>()
+ this.uiServices = new Map<ProtocolVersion, AbstractUIService>()
}
- public buildProtocolRequest(
+ public buildProtocolRequest (
id: string,
procedureName: ProcedureName,
- requestPayload: RequestPayload,
+ requestPayload: RequestPayload
): ProtocolRequest {
- return [id, procedureName, requestPayload];
+ return [id, procedureName, requestPayload]
}
- public buildProtocolResponse(id: string, responsePayload: ResponsePayload): ProtocolResponse {
- return [id, responsePayload];
+ public buildProtocolResponse (id: string, responsePayload: ResponsePayload): ProtocolResponse {
+ return [id, responsePayload]
}
- public stop(): void {
- this.stopHttpServer();
- this.chargingStations.clear();
+ public stop (): void {
+ this.stopHttpServer()
+ this.chargingStations.clear()
}
- public async sendInternalRequest(request: ProtocolRequest): Promise<ProtocolResponse> {
- const protocolVersion = ProtocolVersion['0.0.1'];
- this.registerProtocolVersionUIService(protocolVersion);
- return this.uiServices
+ public async sendInternalRequest (request: ProtocolRequest): Promise<ProtocolResponse> {
+ const protocolVersion = ProtocolVersion['0.0.1']
+ this.registerProtocolVersionUIService(protocolVersion)
+ return await (this.uiServices
.get(protocolVersion)
- ?.requestHandler(request) as Promise<ProtocolResponse>;
+ ?.requestHandler(request) as Promise<ProtocolResponse>)
}
- public hasResponseHandler(id: string): boolean {
- return this.responseHandlers.has(id);
+ public hasResponseHandler (id: string): boolean {
+ return this.responseHandlers.has(id)
}
- protected startHttpServer(): void {
- if (this.httpServer.listening === false) {
- this.httpServer.listen(this.uiServerConfiguration.options);
+ protected startHttpServer (): void {
+ if (!this.httpServer.listening) {
+ this.httpServer.listen(this.uiServerConfiguration.options)
}
}
- protected registerProtocolVersionUIService(version: ProtocolVersion): void {
- if (this.uiServices.has(version) === false) {
- this.uiServices.set(version, UIServiceFactory.getUIServiceImplementation(version, this));
+ protected registerProtocolVersionUIService (version: ProtocolVersion): void {
+ if (!this.uiServices.has(version)) {
+ this.uiServices.set(version, UIServiceFactory.getUIServiceImplementation(version, this))
}
}
- protected authenticate(req: IncomingMessage, next: (err?: Error) => void): void {
- if (this.isBasicAuthEnabled() === true) {
- if (this.isValidBasicAuth(req) === false) {
- next(new BaseError('Unauthorized'));
+ protected authenticate (req: IncomingMessage, next: (err?: Error) => void): void {
+ if (this.isBasicAuthEnabled()) {
+ if (!this.isValidBasicAuth(req)) {
+ next(new BaseError('Unauthorized'))
}
- next();
+ next()
}
- next();
+ next()
}
- private stopHttpServer(): void {
- if (this.httpServer.listening === true) {
- this.httpServer.close();
+ private stopHttpServer (): void {
+ if (this.httpServer.listening) {
+ this.httpServer.close()
}
}
- private isBasicAuthEnabled(): boolean {
+ private isBasicAuthEnabled (): boolean {
return (
this.uiServerConfiguration.authentication?.enabled === true &&
this.uiServerConfiguration.authentication?.type === AuthenticationType.BASIC_AUTH
- );
+ )
}
- private isValidBasicAuth(req: IncomingMessage): boolean {
- const authorizationHeader = req.headers.authorization ?? '';
- const authorizationToken = authorizationHeader.split(/\s+/).pop() ?? '';
- const authentication = Buffer.from(authorizationToken, 'base64').toString();
- const authenticationParts = authentication.split(/:/);
- const username = authenticationParts.shift();
- const password = authenticationParts.join(':');
+ private isValidBasicAuth (req: IncomingMessage): boolean {
+ const authorizationHeader = req.headers.authorization ?? ''
+ const authorizationToken = authorizationHeader.split(/\s+/).pop() ?? ''
+ const authentication = Buffer.from(authorizationToken, 'base64').toString()
+ const authenticationParts = authentication.split(/:/)
+ const username = authenticationParts.shift()
+ const password = authenticationParts.join(':')
return (
this.uiServerConfiguration.authentication?.username === username &&
this.uiServerConfiguration.authentication?.password === password
- );
+ )
}
- public abstract start(): void;
- public abstract sendRequest(request: ProtocolRequest): void;
- public abstract sendResponse(response: ProtocolResponse): void;
- public abstract logPrefix(
- moduleName?: string,
- methodName?: string,
- prefixSuffix?: string,
- ): string;
+ public abstract start (): void
+ public abstract sendRequest (request: ProtocolRequest): void
+ public abstract sendResponse (response: ProtocolResponse): void
+ public abstract logPrefix (moduleName?: string, methodName?: string, prefixSuffix?: string): string
}
-import type { IncomingMessage, RequestListener, ServerResponse } from 'node:http';
+import type { IncomingMessage, RequestListener, ServerResponse } from 'node:http'
-import { StatusCodes } from 'http-status-codes';
+import { StatusCodes } from 'http-status-codes'
-import { AbstractUIServer } from './AbstractUIServer.js';
-import { UIServerUtils } from './UIServerUtils.js';
-import { BaseError } from '../../exception/index.js';
+import { AbstractUIServer } from './AbstractUIServer.js'
+import { UIServerUtils } from './UIServerUtils.js'
+import { BaseError } from '../../exception/index.js'
import {
ApplicationProtocolVersion,
type ProcedureName,
type ProtocolVersion,
type RequestPayload,
ResponseStatus,
- type UIServerConfiguration,
-} from '../../types/index.js';
-import {
- Constants,
- generateUUID,
- isNotEmptyString,
- isNullOrUndefined,
- logPrefix,
- logger,
-} from '../../utils/index.js';
+ type UIServerConfiguration
+} from '../../types/index.js'
+import { Constants, generateUUID, isNotEmptyString, logPrefix, logger } from '../../utils/index.js'
-const moduleName = 'UIHttpServer';
+const moduleName = 'UIHttpServer'
enum HttpMethods {
GET = 'GET',
PUT = 'PUT',
POST = 'POST',
- PATCH = 'PATCH',
+ PATCH = 'PATCH'
}
export class UIHttpServer extends AbstractUIServer {
- public constructor(protected readonly uiServerConfiguration: UIServerConfiguration) {
- super(uiServerConfiguration);
+ public constructor (protected readonly uiServerConfiguration: UIServerConfiguration) {
+ super(uiServerConfiguration)
}
- public start(): void {
- this.httpServer.on('request', this.requestListener.bind(this) as RequestListener);
- this.startHttpServer();
+ public start (): void {
+ this.httpServer.on('request', this.requestListener.bind(this) as RequestListener)
+ this.startHttpServer()
}
- public sendRequest(request: ProtocolRequest): void {
+ public sendRequest (request: ProtocolRequest): void {
switch (this.uiServerConfiguration.version) {
case ApplicationProtocolVersion.VERSION_20:
- this.httpServer.emit('request', request);
- break;
+ this.httpServer.emit('request', request)
+ break
}
}
- public sendResponse(response: ProtocolResponse): void {
- const [uuid, payload] = response;
+ public sendResponse (response: ProtocolResponse): void {
+ const [uuid, payload] = response
try {
- if (this.hasResponseHandler(uuid) === true) {
- const res = this.responseHandlers.get(uuid) as ServerResponse;
+ if (this.hasResponseHandler(uuid)) {
+ const res = this.responseHandlers.get(uuid) as ServerResponse
res
.writeHead(this.responseStatusToStatusCode(payload.status), {
- 'Content-Type': 'application/json',
+ 'Content-Type': 'application/json'
})
- .end(JSON.stringify(payload));
+ .end(JSON.stringify(payload))
} else {
logger.error(
- `${this.logPrefix(moduleName, 'sendResponse')} Response for unknown request id: ${uuid}`,
- );
+ `${this.logPrefix(moduleName, 'sendResponse')} Response for unknown request id: ${uuid}`
+ )
}
} catch (error) {
logger.error(
`${this.logPrefix(moduleName, 'sendResponse')} Error at sending response id '${uuid}':`,
- error,
- );
+ error
+ )
} finally {
- this.responseHandlers.delete(uuid);
+ this.responseHandlers.delete(uuid)
}
}
public logPrefix = (modName?: string, methodName?: string, prefixSuffix?: string): string => {
- const logMsgPrefix = prefixSuffix ? `UI HTTP Server ${prefixSuffix}` : 'UI HTTP Server';
+ const logMsgPrefix = prefixSuffix != null ? `UI HTTP Server ${prefixSuffix}` : 'UI HTTP Server'
const logMsg =
isNotEmptyString(modName) && isNotEmptyString(methodName)
? ` ${logMsgPrefix} | ${modName}.${methodName}:`
- : ` ${logMsgPrefix} |`;
- return logPrefix(logMsg);
- };
+ : ` ${logMsgPrefix} |`
+ return logPrefix(logMsg)
+ }
- private requestListener(req: IncomingMessage, res: ServerResponse): void {
+ private requestListener (req: IncomingMessage, res: ServerResponse): void {
this.authenticate(req, (err) => {
- if (err) {
+ if (err != null) {
res
.writeHead(StatusCodes.UNAUTHORIZED, {
'Content-Type': 'text/plain',
- 'WWW-Authenticate': 'Basic realm=users',
+ 'WWW-Authenticate': 'Basic realm=users'
})
.end(`${StatusCodes.UNAUTHORIZED} Unauthorized`)
- .destroy();
- req.destroy();
+ .destroy()
+ req.destroy()
}
- });
+ })
// Expected request URL pathname: /ui/:version/:procedureName
const [protocol, version, procedureName] = req.url?.split('/').slice(1) as [
Protocol,
ProtocolVersion,
- ProcedureName,
- ];
- const uuid = generateUUID();
- this.responseHandlers.set(uuid, res);
+ ProcedureName
+ ]
+ const uuid = generateUUID()
+ this.responseHandlers.set(uuid, res)
try {
- const fullProtocol = `${protocol}${version}`;
- if (UIServerUtils.isProtocolAndVersionSupported(fullProtocol) === false) {
- throw new BaseError(`Unsupported UI protocol version: '${fullProtocol}'`);
+ const fullProtocol = `${protocol}${version}`
+ if (!UIServerUtils.isProtocolAndVersionSupported(fullProtocol)) {
+ throw new BaseError(`Unsupported UI protocol version: '${fullProtocol}'`)
}
- this.registerProtocolVersionUIService(version);
+ this.registerProtocolVersionUIService(version)
req.on('error', (error) => {
logger.error(
`${this.logPrefix(moduleName, 'requestListener.req.onerror')} Error on HTTP request:`,
- error,
- );
- });
+ error
+ )
+ })
if (req.method === HttpMethods.POST) {
- const bodyBuffer: Uint8Array[] = [];
+ const bodyBuffer: Uint8Array[] = []
req
.on('data', (chunk: Uint8Array) => {
- bodyBuffer.push(chunk);
+ bodyBuffer.push(chunk)
})
.on('end', () => {
- const body = JSON.parse(Buffer.concat(bodyBuffer).toString()) as RequestPayload;
+ const body = JSON.parse(Buffer.concat(bodyBuffer).toString()) as RequestPayload
this.uiServices
.get(version)
?.requestHandler(
this.buildProtocolRequest(
uuid,
procedureName,
- body ?? Constants.EMPTY_FROZEN_OBJECT,
- ),
+ body ?? Constants.EMPTY_FROZEN_OBJECT
+ )
)
.then((protocolResponse?: ProtocolResponse) => {
- if (!isNullOrUndefined(protocolResponse)) {
- this.sendResponse(protocolResponse!);
+ if (protocolResponse != null) {
+ this.sendResponse(protocolResponse)
}
})
- .catch(Constants.EMPTY_FUNCTION);
- });
+ .catch(Constants.EMPTY_FUNCTION)
+ })
} else {
- throw new BaseError(`Unsupported HTTP method: '${req.method}'`);
+ throw new BaseError(`Unsupported HTTP method: '${req.method}'`)
}
} catch (error) {
logger.error(
`${this.logPrefix(moduleName, 'requestListener')} Handle HTTP request error:`,
- error,
- );
- this.sendResponse(this.buildProtocolResponse(uuid, { status: ResponseStatus.FAILURE }));
+ error
+ )
+ this.sendResponse(this.buildProtocolResponse(uuid, { status: ResponseStatus.FAILURE }))
}
}
- private responseStatusToStatusCode(status: ResponseStatus): StatusCodes {
+ private responseStatusToStatusCode (status: ResponseStatus): StatusCodes {
switch (status) {
case ResponseStatus.SUCCESS:
- return StatusCodes.OK;
+ return StatusCodes.OK
case ResponseStatus.FAILURE:
- return StatusCodes.BAD_REQUEST;
+ return StatusCodes.BAD_REQUEST
default:
- return StatusCodes.INTERNAL_SERVER_ERROR;
+ return StatusCodes.INTERNAL_SERVER_ERROR
}
}
}
-import chalk from 'chalk';
+import chalk from 'chalk'
-import type { AbstractUIServer } from './AbstractUIServer.js';
-import { UIHttpServer } from './UIHttpServer.js';
-import { UIServerUtils } from './UIServerUtils.js';
-import { UIWebSocketServer } from './UIWebSocketServer.js';
+import type { AbstractUIServer } from './AbstractUIServer.js'
+import { UIHttpServer } from './UIHttpServer.js'
+import { UIServerUtils } from './UIServerUtils.js'
+import { UIWebSocketServer } from './UIWebSocketServer.js'
import {
ApplicationProtocol,
ApplicationProtocolVersion,
- type UIServerConfiguration,
-} from '../../types/index.js';
+ type UIServerConfiguration
+} from '../../types/index.js'
+// eslint-disable-next-line @typescript-eslint/no-extraneous-class
export class UIServerFactory {
- private constructor() {
+ private constructor () {
// This is intentional
}
- public static getUIServerImplementation(
- uiServerConfiguration: UIServerConfiguration,
+ public static getUIServerImplementation (
+ uiServerConfiguration: UIServerConfiguration
): AbstractUIServer | undefined {
- if (UIServerUtils.isLoopback(uiServerConfiguration.options!.host!) === false) {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ if (!UIServerUtils.isLoopback(uiServerConfiguration.options!.host!)) {
console.warn(
chalk.yellow(
- 'Loopback address not detected in UI server configuration. This is not recommended.',
- ),
- );
+ 'Loopback address not detected in UI server configuration. This is not recommended.'
+ )
+ )
}
uiServerConfiguration = {
version: ApplicationProtocolVersion.VERSION_11,
- ...uiServerConfiguration,
- };
+ ...uiServerConfiguration
+ }
if (
uiServerConfiguration.type === ApplicationProtocol.WS &&
uiServerConfiguration.version !== ApplicationProtocolVersion.VERSION_11
) {
console.warn(
chalk.yellow(
- `Only version ${ApplicationProtocolVersion.VERSION_11} is supported for WebSocket UI server. Falling back to version ${ApplicationProtocolVersion.VERSION_11}.`,
- ),
- );
- uiServerConfiguration.version = ApplicationProtocolVersion.VERSION_11;
+ `Only version ${ApplicationProtocolVersion.VERSION_11} is supported for WebSocket UI server. Falling back to version ${ApplicationProtocolVersion.VERSION_11}.`
+ )
+ )
+ uiServerConfiguration.version = ApplicationProtocolVersion.VERSION_11
}
switch (uiServerConfiguration.type) {
case ApplicationProtocol.WS:
- return new UIWebSocketServer(uiServerConfiguration);
+ return new UIWebSocketServer(uiServerConfiguration)
case ApplicationProtocol.HTTP:
- return new UIHttpServer(uiServerConfiguration);
+ return new UIHttpServer(uiServerConfiguration)
}
}
}
-import type { IncomingMessage } from 'node:http';
+import type { IncomingMessage } from 'node:http'
-import { Protocol, ProtocolVersion } from '../../types/index.js';
-import { logPrefix, logger } from '../../utils/index.js';
+import { Protocol, ProtocolVersion } from '../../types/index.js'
+import { logPrefix, logger } from '../../utils/index.js'
+// eslint-disable-next-line @typescript-eslint/no-extraneous-class
export class UIServerUtils {
- private constructor() {
+ private constructor () {
// This is intentional
}
public static handleProtocols = (
protocols: Set<string>,
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
- request: IncomingMessage,
+ request: IncomingMessage
): string | false => {
- let protocol: Protocol | undefined;
- let version: ProtocolVersion | undefined;
+ let protocol: Protocol | undefined
+ let version: ProtocolVersion | undefined
if (protocols.size === 0) {
- return false;
+ return false
}
for (const fullProtocol of protocols) {
- if (UIServerUtils.isProtocolAndVersionSupported(fullProtocol) === true) {
- return fullProtocol;
+ if (UIServerUtils.isProtocolAndVersionSupported(fullProtocol)) {
+ return fullProtocol
}
}
logger.error(
`${logPrefix(
- ' UI WebSocket Server |',
- )} Unsupported protocol: '${protocol}' or protocol version: '${version}'`,
- );
- return false;
- };
+ ' UI WebSocket Server |'
+ )} Unsupported protocol: '${protocol}' or protocol version: '${version}'`
+ )
+ return false
+ }
public static isProtocolAndVersionSupported = (protocolStr: string): boolean => {
- const [protocol, version] = UIServerUtils.getProtocolAndVersion(protocolStr);
+ const [protocol, version] = UIServerUtils.getProtocolAndVersion(protocolStr)
return (
- Object.values(Protocol).includes(protocol) === true &&
- Object.values(ProtocolVersion).includes(version) === true
- );
- };
+ Object.values(Protocol).includes(protocol) && Object.values(ProtocolVersion).includes(version)
+ )
+ }
public static getProtocolAndVersion = (protocolStr: string): [Protocol, ProtocolVersion] => {
- const protocolIndex = protocolStr.indexOf(Protocol.UI);
+ const protocolIndex = protocolStr.indexOf(Protocol.UI)
const protocol = protocolStr.substring(
protocolIndex,
- protocolIndex + Protocol.UI.length,
- ) as Protocol;
- const version = protocolStr.substring(protocolIndex + Protocol.UI.length) as ProtocolVersion;
- return [protocol, version];
- };
+ protocolIndex + Protocol.UI.length
+ ) as Protocol
+ const version = protocolStr.substring(protocolIndex + Protocol.UI.length) as ProtocolVersion
+ return [protocol, version]
+ }
- public static isLoopback(address: string): boolean {
+ public static isLoopback (address: string): boolean {
+ // eslint-disable-next-line prefer-regex-literals
const isLoopbackRegExp = new RegExp(
// eslint-disable-next-line no-useless-escape
/^localhost$|^127(?:\.\d+){0,2}\.\d+$|^(?:0*\:)*?:?0*1$/,
- 'i',
- );
- return isLoopbackRegExp.test(address);
+ 'i'
+ )
+ return isLoopbackRegExp.test(address)
}
}
-import type { IncomingMessage } from 'node:http';
-import type { Duplex } from 'node:stream';
+import type { IncomingMessage } from 'node:http'
+import type { Duplex } from 'node:stream'
-import { StatusCodes } from 'http-status-codes';
-import { type RawData, WebSocket, WebSocketServer } from 'ws';
+import { StatusCodes } from 'http-status-codes'
+import { type RawData, WebSocket, WebSocketServer } from 'ws'
-import { AbstractUIServer } from './AbstractUIServer.js';
-import { UIServerUtils } from './UIServerUtils.js';
+import { AbstractUIServer } from './AbstractUIServer.js'
+import { UIServerUtils } from './UIServerUtils.js'
import {
type ProtocolRequest,
type ProtocolResponse,
type UIServerConfiguration,
- WebSocketCloseEventStatusCode,
-} from '../../types/index.js';
+ WebSocketCloseEventStatusCode
+} from '../../types/index.js'
import {
Constants,
getWebSocketCloseEventStatusString,
isNotEmptyString,
- isNullOrUndefined,
logPrefix,
logger,
- validateUUID,
-} from '../../utils/index.js';
+ validateUUID
+} from '../../utils/index.js'
-const moduleName = 'UIWebSocketServer';
+const moduleName = 'UIWebSocketServer'
export class UIWebSocketServer extends AbstractUIServer {
- private readonly webSocketServer: WebSocketServer;
+ private readonly webSocketServer: WebSocketServer
- public constructor(protected readonly uiServerConfiguration: UIServerConfiguration) {
- super(uiServerConfiguration);
+ public constructor (protected readonly uiServerConfiguration: UIServerConfiguration) {
+ super(uiServerConfiguration)
this.webSocketServer = new WebSocketServer({
handleProtocols: UIServerUtils.handleProtocols,
- noServer: true,
- });
+ noServer: true
+ })
}
- public start(): void {
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
- this.webSocketServer.on('connection', (ws: WebSocket, req: IncomingMessage): void => {
- if (UIServerUtils.isProtocolAndVersionSupported(ws.protocol) === false) {
+ public start (): void {
+ this.webSocketServer.on('connection', (ws: WebSocket, _req: IncomingMessage): void => {
+ if (!UIServerUtils.isProtocolAndVersionSupported(ws.protocol)) {
logger.error(
`${this.logPrefix(
moduleName,
- 'start.server.onconnection',
- )} Unsupported UI protocol version: '${ws.protocol}'`,
- );
- ws.close(WebSocketCloseEventStatusCode.CLOSE_PROTOCOL_ERROR);
+ 'start.server.onconnection'
+ )} Unsupported UI protocol version: '${ws.protocol}'`
+ )
+ ws.close(WebSocketCloseEventStatusCode.CLOSE_PROTOCOL_ERROR)
}
- const [, version] = UIServerUtils.getProtocolAndVersion(ws.protocol);
- this.registerProtocolVersionUIService(version);
+ const [, version] = UIServerUtils.getProtocolAndVersion(ws.protocol)
+ this.registerProtocolVersionUIService(version)
ws.on('message', (rawData) => {
- const request = this.validateRawDataRequest(rawData);
+ const request = this.validateRawDataRequest(rawData)
if (request === false) {
- ws.close(WebSocketCloseEventStatusCode.CLOSE_INVALID_PAYLOAD);
- return;
+ ws.close(WebSocketCloseEventStatusCode.CLOSE_INVALID_PAYLOAD)
+ return
}
- const [requestId] = request as ProtocolRequest;
- this.responseHandlers.set(requestId, ws);
+ const [requestId] = request as ProtocolRequest
+ this.responseHandlers.set(requestId, ws)
this.uiServices
.get(version)
?.requestHandler(request)
.then((protocolResponse?: ProtocolResponse) => {
- if (!isNullOrUndefined(protocolResponse)) {
- this.sendResponse(protocolResponse!);
+ if (protocolResponse != null) {
+ this.sendResponse(protocolResponse)
}
})
- .catch(Constants.EMPTY_FUNCTION);
- });
+ .catch(Constants.EMPTY_FUNCTION)
+ })
ws.on('error', (error) => {
- logger.error(`${this.logPrefix(moduleName, 'start.ws.onerror')} WebSocket error:`, error);
- });
+ logger.error(`${this.logPrefix(moduleName, 'start.ws.onerror')} WebSocket error:`, error)
+ })
ws.on('close', (code, reason) => {
logger.debug(
`${this.logPrefix(
moduleName,
- 'start.ws.onclose',
+ 'start.ws.onclose'
)} WebSocket closed: '${getWebSocketCloseEventStatusString(
- code,
- )}' - '${reason.toString()}'`,
- );
- });
- });
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
- this.httpServer.on('connect', (req: IncomingMessage, socket: Duplex, head: Buffer) => {
+ code
+ )}' - '${reason.toString()}'`
+ )
+ })
+ })
+ this.httpServer.on('connect', (req: IncomingMessage, socket: Duplex, _head: Buffer) => {
if (req.headers?.connection !== 'Upgrade' || req.headers?.upgrade !== 'websocket') {
- socket.write(`HTTP/1.1 ${StatusCodes.BAD_REQUEST} Bad Request\r\n\r\n`);
- socket.destroy();
+ socket.write(`HTTP/1.1 ${StatusCodes.BAD_REQUEST} Bad Request\r\n\r\n`)
+ socket.destroy()
}
- });
+ })
this.httpServer.on('upgrade', (req: IncomingMessage, socket: Duplex, head: Buffer): void => {
this.authenticate(req, (err) => {
- if (err) {
- socket.write(`HTTP/1.1 ${StatusCodes.UNAUTHORIZED} Unauthorized\r\n\r\n`);
- socket.destroy();
- return;
+ if (err != null) {
+ socket.write(`HTTP/1.1 ${StatusCodes.UNAUTHORIZED} Unauthorized\r\n\r\n`)
+ socket.destroy()
+ return
}
try {
this.webSocketServer.handleUpgrade(req, socket, head, (ws: WebSocket) => {
- this.webSocketServer.emit('connection', ws, req);
- });
+ this.webSocketServer.emit('connection', ws, req)
+ })
} catch (error) {
logger.error(
`${this.logPrefix(
moduleName,
- 'start.httpServer.on.upgrade',
+ 'start.httpServer.on.upgrade'
)} Error at handling connection upgrade:`,
- error,
- );
+ error
+ )
}
- });
- });
- this.startHttpServer();
+ })
+ })
+ this.startHttpServer()
}
- public sendRequest(request: ProtocolRequest): void {
- this.broadcastToClients(JSON.stringify(request));
+ public sendRequest (request: ProtocolRequest): void {
+ this.broadcastToClients(JSON.stringify(request))
}
- public sendResponse(response: ProtocolResponse): void {
- const responseId = response?.[0];
+ public sendResponse (response: ProtocolResponse): void {
+ const responseId = response?.[0]
try {
if (this.hasResponseHandler(responseId)) {
- const ws = this.responseHandlers.get(responseId) as WebSocket;
+ const ws = this.responseHandlers.get(responseId) as WebSocket
if (ws?.readyState === WebSocket.OPEN) {
- ws.send(JSON.stringify(response));
+ ws.send(JSON.stringify(response))
} else {
logger.error(
`${this.logPrefix(
moduleName,
- 'sendResponse',
- )} Error at sending response id '${responseId}', WebSocket is not open: ${ws?.readyState}`,
- );
+ 'sendResponse'
+ )} Error at sending response id '${responseId}', WebSocket is not open: ${ws?.readyState}`
+ )
}
} else {
logger.error(
`${this.logPrefix(
moduleName,
- 'sendResponse',
- )} Response for unknown request id: ${responseId}`,
- );
+ 'sendResponse'
+ )} Response for unknown request id: ${responseId}`
+ )
}
} catch (error) {
logger.error(
`${this.logPrefix(
moduleName,
- 'sendResponse',
+ 'sendResponse'
)} Error at sending response id '${responseId}':`,
- error,
- );
+ error
+ )
} finally {
- this.responseHandlers.delete(responseId);
+ this.responseHandlers.delete(responseId)
}
}
public logPrefix = (modName?: string, methodName?: string, prefixSuffix?: string): string => {
- const logMsgPrefix = prefixSuffix
- ? `UI WebSocket Server ${prefixSuffix}`
- : 'UI WebSocket Server';
+ const logMsgPrefix =
+ prefixSuffix != null ? `UI WebSocket Server ${prefixSuffix}` : 'UI WebSocket Server'
const logMsg =
isNotEmptyString(modName) && isNotEmptyString(methodName)
? ` ${logMsgPrefix} | ${modName}.${methodName}:`
- : ` ${logMsgPrefix} |`;
- return logPrefix(logMsg);
- };
+ : ` ${logMsgPrefix} |`
+ return logPrefix(logMsg)
+ }
- private broadcastToClients(message: string): void {
+ private broadcastToClients (message: string): void {
for (const client of this.webSocketServer.clients) {
if (client?.readyState === WebSocket.OPEN) {
- client.send(message);
+ client.send(message)
}
}
}
- private validateRawDataRequest(rawData: RawData): ProtocolRequest | false {
+ private validateRawDataRequest (rawData: RawData): ProtocolRequest | false {
// logger.debug(
// `${this.logPrefix(
// moduleName,
- // 'validateRawDataRequest',
+ // 'validateRawDataRequest'
// // eslint-disable-next-line @typescript-eslint/no-base-to-string
- // )} Raw data received in string format: ${rawData.toString()}`,
- // );
+ // )} Raw data received in string format: ${rawData.toString()}`
+ // )
// eslint-disable-next-line @typescript-eslint/no-base-to-string
- const request = JSON.parse(rawData.toString()) as ProtocolRequest;
+ const request = JSON.parse(rawData.toString()) as ProtocolRequest
- if (Array.isArray(request) === false) {
+ if (!Array.isArray(request)) {
logger.error(
`${this.logPrefix(
moduleName,
- 'validateRawDataRequest',
+ 'validateRawDataRequest'
)} UI protocol request is not an array:`,
- request,
- );
- return false;
+ request
+ )
+ return false
}
if (request.length !== 3) {
logger.error(
`${this.logPrefix(moduleName, 'validateRawDataRequest')} UI protocol request is malformed:`,
- request,
- );
- return false;
+ request
+ )
+ return false
}
- if (validateUUID(request?.[0]) === false) {
+ if (!validateUUID(request?.[0])) {
logger.error(
`${this.logPrefix(
moduleName,
- 'validateRawDataRequest',
+ 'validateRawDataRequest'
)} UI protocol request UUID field is invalid:`,
- request,
- );
- return false;
+ request
+ )
+ return false
}
- return request;
+ return request
}
}
-import { BaseError, type OCPPError } from '../../../exception/index.js';
+import { BaseError, type OCPPError } from '../../../exception/index.js'
import {
BroadcastChannelProcedureName,
type BroadcastChannelRequestPayload,
+ type JsonType,
ProcedureName,
type ProtocolRequest,
type ProtocolRequestHandler,
type ProtocolVersion,
type RequestPayload,
type ResponsePayload,
- ResponseStatus,
-} from '../../../types/index.js';
-import { isNotEmptyArray, isNullOrUndefined, logger } from '../../../utils/index.js';
-import { Bootstrap } from '../../Bootstrap.js';
-import { UIServiceWorkerBroadcastChannel } from '../../broadcast-channel/UIServiceWorkerBroadcastChannel.js';
-import type { AbstractUIServer } from '../AbstractUIServer.js';
+ ResponseStatus
+} from '../../../types/index.js'
+import { isNotEmptyArray, isNullOrUndefined, logger } from '../../../utils/index.js'
+import { Bootstrap } from '../../Bootstrap.js'
+import { UIServiceWorkerBroadcastChannel } from '../../broadcast-channel/UIServiceWorkerBroadcastChannel.js'
+import type { AbstractUIServer } from '../AbstractUIServer.js'
-const moduleName = 'AbstractUIService';
+const moduleName = 'AbstractUIService'
export abstract class AbstractUIService {
protected static readonly ProcedureNameToBroadCastChannelProcedureNameMapping = new Map<
- ProcedureName,
- BroadcastChannelProcedureName
+ ProcedureName,
+ BroadcastChannelProcedureName
>([
[ProcedureName.START_CHARGING_STATION, BroadcastChannelProcedureName.START_CHARGING_STATION],
[ProcedureName.STOP_CHARGING_STATION, BroadcastChannelProcedureName.STOP_CHARGING_STATION],
[ProcedureName.OPEN_CONNECTION, BroadcastChannelProcedureName.OPEN_CONNECTION],
[
ProcedureName.START_AUTOMATIC_TRANSACTION_GENERATOR,
- BroadcastChannelProcedureName.START_AUTOMATIC_TRANSACTION_GENERATOR,
+ BroadcastChannelProcedureName.START_AUTOMATIC_TRANSACTION_GENERATOR
],
[
ProcedureName.STOP_AUTOMATIC_TRANSACTION_GENERATOR,
- BroadcastChannelProcedureName.STOP_AUTOMATIC_TRANSACTION_GENERATOR,
+ BroadcastChannelProcedureName.STOP_AUTOMATIC_TRANSACTION_GENERATOR
],
[ProcedureName.SET_SUPERVISION_URL, BroadcastChannelProcedureName.SET_SUPERVISION_URL],
[ProcedureName.START_TRANSACTION, BroadcastChannelProcedureName.START_TRANSACTION],
[ProcedureName.DATA_TRANSFER, BroadcastChannelProcedureName.DATA_TRANSFER],
[
ProcedureName.DIAGNOSTICS_STATUS_NOTIFICATION,
- BroadcastChannelProcedureName.DIAGNOSTICS_STATUS_NOTIFICATION,
+ BroadcastChannelProcedureName.DIAGNOSTICS_STATUS_NOTIFICATION
],
[
ProcedureName.FIRMWARE_STATUS_NOTIFICATION,
- BroadcastChannelProcedureName.FIRMWARE_STATUS_NOTIFICATION,
- ],
- ]);
-
- protected readonly requestHandlers: Map<ProcedureName, ProtocolRequestHandler>;
- private readonly version: ProtocolVersion;
- private readonly uiServer: AbstractUIServer;
- private readonly uiServiceWorkerBroadcastChannel: UIServiceWorkerBroadcastChannel;
- private readonly broadcastChannelRequests: Map<string, number>;
-
- constructor(uiServer: AbstractUIServer, version: ProtocolVersion) {
- this.uiServer = uiServer;
- this.version = version;
+ BroadcastChannelProcedureName.FIRMWARE_STATUS_NOTIFICATION
+ ]
+ ])
+
+ protected readonly requestHandlers: Map<ProcedureName, ProtocolRequestHandler>
+ private readonly version: ProtocolVersion
+ private readonly uiServer: AbstractUIServer
+ private readonly uiServiceWorkerBroadcastChannel: UIServiceWorkerBroadcastChannel
+ private readonly broadcastChannelRequests: Map<string, number>
+
+ constructor (uiServer: AbstractUIServer, version: ProtocolVersion) {
+ this.uiServer = uiServer
+ this.version = version
this.requestHandlers = new Map<ProcedureName, ProtocolRequestHandler>([
[ProcedureName.LIST_CHARGING_STATIONS, this.handleListChargingStations.bind(this)],
[ProcedureName.START_SIMULATOR, this.handleStartSimulator.bind(this)],
- [ProcedureName.STOP_SIMULATOR, this.handleStopSimulator.bind(this)],
- ]);
- this.uiServiceWorkerBroadcastChannel = new UIServiceWorkerBroadcastChannel(this);
- this.broadcastChannelRequests = new Map<string, number>();
+ [ProcedureName.STOP_SIMULATOR, this.handleStopSimulator.bind(this)]
+ ])
+ this.uiServiceWorkerBroadcastChannel = new UIServiceWorkerBroadcastChannel(this)
+ this.broadcastChannelRequests = new Map<string, number>()
}
- public async requestHandler(request: ProtocolRequest): Promise<ProtocolResponse | undefined> {
- let messageId: string | undefined;
- let command: ProcedureName | undefined;
- let requestPayload: RequestPayload | undefined;
- let responsePayload: ResponsePayload | undefined;
+ public async requestHandler (request: ProtocolRequest): Promise<ProtocolResponse | undefined> {
+ let messageId: string | undefined
+ let command: ProcedureName | undefined
+ let requestPayload: RequestPayload | undefined
+ let responsePayload: ResponsePayload | undefined
try {
- [messageId, command, requestPayload] = request;
+ [messageId, command, requestPayload] = request
- if (this.requestHandlers.has(command) === false) {
+ if (!this.requestHandlers.has(command)) {
throw new BaseError(
`${command} is not implemented to handle message payload ${JSON.stringify(
requestPayload,
undefined,
- 2,
- )}`,
- );
+ 2
+ )}`
+ )
}
// Call the request handler to build the response payload
- responsePayload = await this.requestHandlers.get(command)!(
- messageId,
- command,
- requestPayload,
- );
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ responsePayload = await this.requestHandlers.get(command)!(messageId, command, requestPayload)
} catch (error) {
// Log
- logger.error(`${this.logPrefix(moduleName, 'requestHandler')} Handle request error:`, error);
+ logger.error(`${this.logPrefix(moduleName, 'requestHandler')} Handle request error:`, error)
responsePayload = {
hashIds: requestPayload?.hashIds,
status: ResponseStatus.FAILURE,
responsePayload,
errorMessage: (error as OCPPError).message,
errorStack: (error as OCPPError).stack,
- errorDetails: (error as OCPPError).details,
- };
+ errorDetails: (error as OCPPError).details
+ }
}
if (!isNullOrUndefined(responsePayload)) {
- return this.uiServer.buildProtocolResponse(messageId!, responsePayload!);
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ return this.uiServer.buildProtocolResponse(messageId!, responsePayload!)
}
}
- // public sendRequest(
+ // public sendRequest (
// messageId: string,
// procedureName: ProcedureName,
- // requestPayload: RequestPayload,
+ // requestPayload: RequestPayload
// ): void {
// this.uiServer.sendRequest(
- // this.uiServer.buildProtocolRequest(messageId, procedureName, requestPayload),
- // );
+ // this.uiServer.buildProtocolRequest(messageId, procedureName, requestPayload)
+ // )
// }
- public sendResponse(messageId: string, responsePayload: ResponsePayload): void {
+ public sendResponse (messageId: string, responsePayload: ResponsePayload): void {
if (this.uiServer.hasResponseHandler(messageId)) {
- this.uiServer.sendResponse(this.uiServer.buildProtocolResponse(messageId, responsePayload));
+ this.uiServer.sendResponse(this.uiServer.buildProtocolResponse(messageId, responsePayload))
}
}
public logPrefix = (modName: string, methodName: string): string => {
- return this.uiServer.logPrefix(modName, methodName, this.version);
- };
+ return this.uiServer.logPrefix(modName, methodName, this.version)
+ }
- public deleteBroadcastChannelRequest(uuid: string): void {
- this.broadcastChannelRequests.delete(uuid);
+ public deleteBroadcastChannelRequest (uuid: string): void {
+ this.broadcastChannelRequests.delete(uuid)
}
- public getBroadcastChannelExpectedResponses(uuid: string): number {
- return this.broadcastChannelRequests.get(uuid)!;
+ public getBroadcastChannelExpectedResponses (uuid: string): number {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ return this.broadcastChannelRequests.get(uuid)!
}
- protected handleProtocolRequest(
+ protected handleProtocolRequest (
uuid: string,
procedureName: ProcedureName,
- payload: RequestPayload,
+ payload: RequestPayload
): void {
this.sendBroadcastChannelRequest(
uuid,
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
AbstractUIService.ProcedureNameToBroadCastChannelProcedureNameMapping.get(procedureName)!,
- payload,
- );
+ payload
+ )
}
- private sendBroadcastChannelRequest(
+ private sendBroadcastChannelRequest (
uuid: string,
procedureName: BroadcastChannelProcedureName,
- payload: BroadcastChannelRequestPayload,
+ payload: BroadcastChannelRequestPayload
): void {
if (isNotEmptyArray(payload.hashIds)) {
payload.hashIds = payload.hashIds
?.map((hashId) => {
- if (hashId !== undefined && this.uiServer.chargingStations.has(hashId) === true) {
- return hashId;
+ if (hashId !== undefined && this.uiServer.chargingStations.has(hashId)) {
+ return hashId
}
logger.warn(
`${this.logPrefix(
moduleName,
- 'sendBroadcastChannelRequest',
- )} Charging station with hashId '${hashId}' not found`,
- );
+ 'sendBroadcastChannelRequest'
+ )} Charging station with hashId '${hashId}' not found`
+ )
+ return undefined
})
- ?.filter((hashId) => !isNullOrUndefined(hashId)) as string[];
+ ?.filter((hashId) => !isNullOrUndefined(hashId)) as string[]
} else {
- delete payload.hashIds;
+ delete payload.hashIds
}
const expectedNumberOfResponses = Array.isArray(payload.hashIds)
? payload.hashIds.length
- : this.uiServer.chargingStations.size;
+ : this.uiServer.chargingStations.size
if (expectedNumberOfResponses === 0) {
throw new BaseError(
- 'hashIds array in the request payload does not contain any valid charging station hashId',
- );
+ 'hashIds array in the request payload does not contain any valid charging station hashId'
+ )
}
- this.uiServiceWorkerBroadcastChannel.sendRequest([uuid, procedureName, payload]);
- this.broadcastChannelRequests.set(uuid, expectedNumberOfResponses);
+ this.uiServiceWorkerBroadcastChannel.sendRequest([uuid, procedureName, payload])
+ this.broadcastChannelRequests.set(uuid, expectedNumberOfResponses)
}
- private handleListChargingStations(): ResponsePayload {
+ private handleListChargingStations (): ResponsePayload {
return {
status: ResponseStatus.SUCCESS,
- chargingStations: [...this.uiServer.chargingStations.values()],
- } as ResponsePayload;
+ chargingStations: [...this.uiServer.chargingStations.values()] as JsonType[]
+ } satisfies ResponsePayload
}
- private async handleStartSimulator(): Promise<ResponsePayload> {
+ private async handleStartSimulator (): Promise<ResponsePayload> {
try {
- await Bootstrap.getInstance().start();
- return { status: ResponseStatus.SUCCESS };
+ await Bootstrap.getInstance().start()
+ return { status: ResponseStatus.SUCCESS }
} catch {
- return { status: ResponseStatus.FAILURE };
+ return { status: ResponseStatus.FAILURE }
}
}
- private async handleStopSimulator(): Promise<ResponsePayload> {
+ private async handleStopSimulator (): Promise<ResponsePayload> {
try {
- await Bootstrap.getInstance().stop();
- return { status: ResponseStatus.SUCCESS };
+ await Bootstrap.getInstance().stop()
+ return { status: ResponseStatus.SUCCESS }
} catch {
- return { status: ResponseStatus.FAILURE };
+ return { status: ResponseStatus.FAILURE }
}
}
}
-import { AbstractUIService } from './AbstractUIService.js';
-import { type ProtocolRequestHandler, ProtocolVersion } from '../../../types/index.js';
-import type { AbstractUIServer } from '../AbstractUIServer.js';
+import { AbstractUIService } from './AbstractUIService.js'
+import { type ProtocolRequestHandler, ProtocolVersion } from '../../../types/index.js'
+import type { AbstractUIServer } from '../AbstractUIServer.js'
export class UIService001 extends AbstractUIService {
- constructor(uiServer: AbstractUIServer) {
- super(uiServer, ProtocolVersion['0.0.1']);
+ constructor (uiServer: AbstractUIServer) {
+ super(uiServer, ProtocolVersion['0.0.1'])
for (const procedureName of AbstractUIService.ProcedureNameToBroadCastChannelProcedureNameMapping.keys()) {
this.requestHandlers.set(
procedureName,
- this.handleProtocolRequest.bind(this) as ProtocolRequestHandler,
- );
+ this.handleProtocolRequest.bind(this) as ProtocolRequestHandler
+ )
}
}
}
-import type { AbstractUIService } from './AbstractUIService.js';
-import { UIService001 } from './UIService001.js';
-import { ProtocolVersion } from '../../../types/index.js';
-import type { AbstractUIServer } from '../AbstractUIServer.js';
+import type { AbstractUIService } from './AbstractUIService.js'
+import { UIService001 } from './UIService001.js'
+import { ProtocolVersion } from '../../../types/index.js'
+import type { AbstractUIServer } from '../AbstractUIServer.js'
+// eslint-disable-next-line @typescript-eslint/no-extraneous-class
export class UIServiceFactory {
- private constructor() {
+ private constructor () {
// This is intentional
}
- public static getUIServiceImplementation(
+ public static getUIServiceImplementation (
version: ProtocolVersion,
- uiServer: AbstractUIServer,
+ uiServer: AbstractUIServer
): AbstractUIService {
switch (version) {
case ProtocolVersion['0.0.1']:
- return new UIService001(uiServer);
+ return new UIService001(uiServer)
}
}
}
export class BaseError extends Error {
- public constructor(message?: string) {
- super(message);
- this.name = new.target.name;
- Object.setPrototypeOf(this, new.target.prototype);
+ public constructor (message?: string) {
+ super(message)
+ this.name = new.target.name
+ Object.setPrototypeOf(this, new.target.prototype)
typeof Error.captureStackTrace === 'function'
? Error.captureStackTrace(this, this.constructor)
- : this.createStack();
+ : this.createStack()
}
- private createStack(): void {
- this.stack = new Error().stack;
+ private createStack (): void {
+ this.stack = new Error().stack
}
}
// Partial Copyright Jerome Benoit. 2021-2023. All Rights Reserved.
-import { BaseError } from './BaseError.js';
+import { BaseError } from './BaseError.js'
import {
- ErrorType,
+ type ErrorType,
type IncomingRequestCommand,
type JsonType,
- type RequestCommand,
-} from '../types/index.js';
-import { Constants } from '../utils/index.js';
+ type RequestCommand
+} from '../types/index.js'
+import { Constants } from '../utils/index.js'
export class OCPPError extends BaseError {
- code: ErrorType;
- command?: RequestCommand | IncomingRequestCommand;
- details?: JsonType;
+ code: ErrorType
+ command?: RequestCommand | IncomingRequestCommand
+ details?: JsonType
- constructor(
+ constructor (
code: ErrorType,
message: string,
command?: RequestCommand | IncomingRequestCommand,
- details?: JsonType,
+ details?: JsonType
) {
- super(message);
+ super(message)
- this.code = code;
- this.command =
- command ?? (Constants.UNKNOWN_COMMAND as RequestCommand | IncomingRequestCommand);
- this.details = details;
+ this.code = code
+ this.command = command ?? (Constants.UNKNOWN_COMMAND as RequestCommand | IncomingRequestCommand)
+ this.details = details
}
}
-export { BaseError } from './BaseError.js';
-export { OCPPError } from './OCPPError.js';
+export { BaseError } from './BaseError.js'
+export { OCPPError } from './OCPPError.js'
// Partial Copyright Jerome Benoit. 2021-2023. All Rights Reserved.
-import { type PerformanceEntry, PerformanceObserver, performance } from 'node:perf_hooks';
-import type { URL } from 'node:url';
-import { parentPort } from 'node:worker_threads';
+import { type PerformanceEntry, PerformanceObserver, performance } from 'node:perf_hooks'
+import type { URL } from 'node:url'
+import { parentPort } from 'node:worker_threads'
-import { secondsToMilliseconds } from 'date-fns';
+import { secondsToMilliseconds } from 'date-fns'
import {
ConfigurationSection,
type RequestCommand,
type Statistics,
type StorageConfiguration,
- type TimestampedData,
-} from '../types/index.js';
+ type TimestampedData
+} from '../types/index.js'
import {
CircularArray,
Configuration,
median,
min,
nthPercentile,
- stdDeviation,
-} from '../utils/index.js';
+ stdDeviation
+} from '../utils/index.js'
export class PerformanceStatistics {
private static readonly instances: Map<string, PerformanceStatistics> = new Map<
- string,
- PerformanceStatistics
- >();
+ string,
+ PerformanceStatistics
+ >()
- private readonly objId: string;
- private readonly objName: string;
- private performanceObserver!: PerformanceObserver;
- private readonly statistics: Statistics;
- private displayInterval?: NodeJS.Timeout;
+ private readonly objId: string
+ private readonly objName: string
+ private performanceObserver!: PerformanceObserver
+ private readonly statistics: Statistics
+ private displayInterval?: NodeJS.Timeout
- private constructor(objId: string, objName: string, uri: URL) {
- this.objId = objId;
- this.objName = objName;
- this.initializePerformanceObserver();
+ private constructor (objId: string, objName: string, uri: URL) {
+ this.objId = objId
+ this.objName = objName
+ this.initializePerformanceObserver()
this.statistics = {
id: this.objId ?? 'Object id not specified',
name: this.objName ?? 'Object name not specified',
uri: uri.toString(),
createdAt: new Date(),
- statisticsData: new Map(),
- };
+ statisticsData: new Map()
+ }
}
- public static getInstance(
+ public static getInstance (
objId: string,
objName: string,
- uri: URL,
+ uri: URL
): PerformanceStatistics | undefined {
if (!PerformanceStatistics.instances.has(objId)) {
- PerformanceStatistics.instances.set(objId, new PerformanceStatistics(objId, objName, uri));
+ PerformanceStatistics.instances.set(objId, new PerformanceStatistics(objId, objName, uri))
}
- return PerformanceStatistics.instances.get(objId);
+ return PerformanceStatistics.instances.get(objId)
}
- public static beginMeasure(id: string): string {
- const markId = `${id.charAt(0).toUpperCase()}${id.slice(1)}~${generateUUID()}`;
- performance.mark(markId);
- return markId;
+ public static beginMeasure (id: string): string {
+ const markId = `${id.charAt(0).toUpperCase()}${id.slice(1)}~${generateUUID()}`
+ performance.mark(markId)
+ return markId
}
- public static endMeasure(name: string, markId: string): void {
+ public static endMeasure (name: string, markId: string): void {
try {
- performance.measure(name, markId);
+ performance.measure(name, markId)
} catch (error) {
if (error instanceof Error && error.message.includes('performance mark has not been set')) {
/** Ignore */
} else {
- throw error;
+ throw error
}
}
- performance.clearMarks(markId);
- performance.clearMeasures(name);
+ performance.clearMarks(markId)
+ performance.clearMeasures(name)
}
- public addRequestStatistic(
+ public addRequestStatistic (
command: RequestCommand | IncomingRequestCommand,
- messageType: MessageType,
+ messageType: MessageType
): void {
switch (messageType) {
case MessageType.CALL_MESSAGE:
if (
this.statistics.statisticsData.has(command) &&
- this.statistics.statisticsData.get(command)?.requestCount
+ this.statistics.statisticsData.get(command)?.requestCount != null
) {
- ++this.statistics.statisticsData.get(command)!.requestCount!;
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ ++this.statistics.statisticsData.get(command)!.requestCount!
} else {
this.statistics.statisticsData.set(command, {
...this.statistics.statisticsData.get(command),
- requestCount: 1,
- });
+ requestCount: 1
+ })
}
- break;
+ break
case MessageType.CALL_RESULT_MESSAGE:
if (
this.statistics.statisticsData.has(command) &&
- this.statistics.statisticsData.get(command)?.responseCount
+ this.statistics.statisticsData.get(command)?.responseCount != null
) {
- ++this.statistics.statisticsData.get(command)!.responseCount!;
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ ++this.statistics.statisticsData.get(command)!.responseCount!
} else {
this.statistics.statisticsData.set(command, {
...this.statistics.statisticsData.get(command),
- responseCount: 1,
- });
+ responseCount: 1
+ })
}
- break;
+ break
case MessageType.CALL_ERROR_MESSAGE:
if (
this.statistics.statisticsData.has(command) &&
- this.statistics.statisticsData.get(command)?.errorCount
+ this.statistics.statisticsData.get(command)?.errorCount != null
) {
- ++this.statistics.statisticsData.get(command)!.errorCount!;
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ ++this.statistics.statisticsData.get(command)!.errorCount!
} else {
this.statistics.statisticsData.set(command, {
...this.statistics.statisticsData.get(command),
- errorCount: 1,
- });
+ errorCount: 1
+ })
}
- break;
+ break
default:
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
- logger.error(`${this.logPrefix()} wrong message type ${messageType}`);
- break;
+ logger.error(`${this.logPrefix()} wrong message type ${messageType}`)
+ break
}
}
- public start(): void {
- this.startLogStatisticsInterval();
+ public start (): void {
+ this.startLogStatisticsInterval()
const performanceStorageConfiguration =
Configuration.getConfigurationSection<StorageConfiguration>(
- ConfigurationSection.performanceStorage,
- );
- if (performanceStorageConfiguration.enabled) {
+ ConfigurationSection.performanceStorage
+ )
+ if (performanceStorageConfiguration.enabled === true) {
logger.info(
`${this.logPrefix()} storage enabled: type ${performanceStorageConfiguration.type}, uri: ${
performanceStorageConfiguration.uri
- }`,
- );
+ }`
+ )
}
}
- public stop(): void {
- this.stopLogStatisticsInterval();
- performance.clearMarks();
- performance.clearMeasures();
- this.performanceObserver?.disconnect();
+ public stop (): void {
+ this.stopLogStatisticsInterval()
+ performance.clearMarks()
+ performance.clearMeasures()
+ this.performanceObserver?.disconnect()
}
- public restart(): void {
- this.stop();
- this.start();
+ public restart (): void {
+ this.stop()
+ this.start()
}
- private initializePerformanceObserver(): void {
+ private initializePerformanceObserver (): void {
this.performanceObserver = new PerformanceObserver((performanceObserverList) => {
- const lastPerformanceEntry = performanceObserverList.getEntries()[0];
+ const lastPerformanceEntry = performanceObserverList.getEntries()[0]
// logger.debug(
// `${this.logPrefix()} '${lastPerformanceEntry.name}' performance entry: %j`,
- // lastPerformanceEntry,
- // );
- this.addPerformanceEntryToStatistics(lastPerformanceEntry);
- });
- this.performanceObserver.observe({ entryTypes: ['measure'] });
+ // lastPerformanceEntry
+ // )
+ this.addPerformanceEntryToStatistics(lastPerformanceEntry)
+ })
+ this.performanceObserver.observe({ entryTypes: ['measure'] })
}
- private logStatistics(): void {
+ private logStatistics (): void {
logger.info(`${this.logPrefix()}`, {
...this.statistics,
- statisticsData: JSONStringifyWithMapSupport(this.statistics.statisticsData),
- });
+ statisticsData: JSONStringifyWithMapSupport(this.statistics.statisticsData)
+ })
}
- private startLogStatisticsInterval(): void {
+ private startLogStatisticsInterval (): void {
const logConfiguration = Configuration.getConfigurationSection<LogConfiguration>(
- ConfigurationSection.log,
- );
- const logStatisticsInterval = logConfiguration.enabled
- ? logConfiguration.statisticsInterval!
- : 0;
- if (logStatisticsInterval > 0 && !this.displayInterval) {
+ ConfigurationSection.log
+ )
+ const logStatisticsInterval =
+ logConfiguration.enabled === true
+ ? // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ logConfiguration.statisticsInterval!
+ : 0
+ if (logStatisticsInterval > 0 && this.displayInterval == null) {
this.displayInterval = setInterval(() => {
- this.logStatistics();
- }, secondsToMilliseconds(logStatisticsInterval));
+ this.logStatistics()
+ }, secondsToMilliseconds(logStatisticsInterval))
logger.info(
- `${this.logPrefix()} logged every ${formatDurationSeconds(logStatisticsInterval)}`,
- );
- } else if (this.displayInterval) {
+ `${this.logPrefix()} logged every ${formatDurationSeconds(logStatisticsInterval)}`
+ )
+ } else if (this.displayInterval != null) {
logger.info(
- `${this.logPrefix()} already logged every ${formatDurationSeconds(logStatisticsInterval)}`,
- );
- } else if (logConfiguration.enabled) {
+ `${this.logPrefix()} already logged every ${formatDurationSeconds(logStatisticsInterval)}`
+ )
+ } else if (logConfiguration.enabled === true) {
logger.info(
- `${this.logPrefix()} log interval is set to ${logStatisticsInterval}. Not logging statistics`,
- );
+ `${this.logPrefix()} log interval is set to ${logStatisticsInterval}. Not logging statistics`
+ )
}
}
- private stopLogStatisticsInterval(): void {
- if (this.displayInterval) {
- clearInterval(this.displayInterval);
- delete this.displayInterval;
+ private stopLogStatisticsInterval (): void {
+ if (this.displayInterval != null) {
+ clearInterval(this.displayInterval)
+ delete this.displayInterval
}
}
- private addPerformanceEntryToStatistics(entry: PerformanceEntry): void {
+ private addPerformanceEntryToStatistics (entry: PerformanceEntry): void {
// Initialize command statistics
if (!this.statistics.statisticsData.has(entry.name)) {
- this.statistics.statisticsData.set(entry.name, {});
+ this.statistics.statisticsData.set(entry.name, {})
}
// Update current statistics
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.statistics.statisticsData.get(entry.name)!.timeMeasurementCount =
- (this.statistics.statisticsData.get(entry.name)?.timeMeasurementCount ?? 0) + 1;
- this.statistics.statisticsData.get(entry.name)!.currentTimeMeasurement = entry.duration;
+ (this.statistics.statisticsData.get(entry.name)?.timeMeasurementCount ?? 0) + 1
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ this.statistics.statisticsData.get(entry.name)!.currentTimeMeasurement = entry.duration
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.statistics.statisticsData.get(entry.name)!.minTimeMeasurement = min(
entry.duration,
- this.statistics.statisticsData.get(entry.name)?.minTimeMeasurement ?? Infinity,
- );
+ this.statistics.statisticsData.get(entry.name)?.minTimeMeasurement ?? Infinity
+ )
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.statistics.statisticsData.get(entry.name)!.maxTimeMeasurement = max(
entry.duration,
- this.statistics.statisticsData.get(entry.name)?.maxTimeMeasurement ?? -Infinity,
- );
+ this.statistics.statisticsData.get(entry.name)?.maxTimeMeasurement ?? -Infinity
+ )
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.statistics.statisticsData.get(entry.name)!.totalTimeMeasurement =
- (this.statistics.statisticsData.get(entry.name)?.totalTimeMeasurement ?? 0) + entry.duration;
+ (this.statistics.statisticsData.get(entry.name)?.totalTimeMeasurement ?? 0) + entry.duration
this.statistics.statisticsData.get(entry.name)?.measurementTimeSeries instanceof CircularArray
? this.statistics.statisticsData
- .get(entry.name)
- ?.measurementTimeSeries?.push({ timestamp: entry.startTime, value: entry.duration })
- : (this.statistics.statisticsData.get(entry.name)!.measurementTimeSeries =
+ .get(entry.name)
+ ?.measurementTimeSeries?.push({ timestamp: entry.startTime, value: entry.duration })
+ : // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ (this.statistics.statisticsData.get(entry.name)!.measurementTimeSeries =
new CircularArray<TimestampedData>(Constants.DEFAULT_CIRCULAR_BUFFER_CAPACITY, {
timestamp: entry.startTime,
- value: entry.duration,
- }));
+ value: entry.duration
+ }))
const timeMeasurementValues = extractTimeSeriesValues(
- this.statistics.statisticsData.get(entry.name)!.measurementTimeSeries!,
- );
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ this.statistics.statisticsData.get(entry.name)!.measurementTimeSeries!
+ )
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.statistics.statisticsData.get(entry.name)!.avgTimeMeasurement =
- average(timeMeasurementValues);
+ average(timeMeasurementValues)
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.statistics.statisticsData.get(entry.name)!.medTimeMeasurement =
- median(timeMeasurementValues);
+ median(timeMeasurementValues)
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.statistics.statisticsData.get(entry.name)!.ninetyFiveThPercentileTimeMeasurement =
- nthPercentile(timeMeasurementValues, 95);
+ nthPercentile(timeMeasurementValues, 95)
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.statistics.statisticsData.get(entry.name)!.stdDevTimeMeasurement = stdDeviation(
timeMeasurementValues,
- this.statistics.statisticsData.get(entry.name)!.avgTimeMeasurement,
- );
- this.statistics.updatedAt = new Date();
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ this.statistics.statisticsData.get(entry.name)!.avgTimeMeasurement
+ )
+ this.statistics.updatedAt = new Date()
if (
Configuration.getConfigurationSection<StorageConfiguration>(
- ConfigurationSection.performanceStorage,
- ).enabled
+ ConfigurationSection.performanceStorage
+ ).enabled === true
) {
- parentPort?.postMessage(buildPerformanceStatisticsMessage(this.statistics));
+ parentPort?.postMessage(buildPerformanceStatisticsMessage(this.statistics))
}
}
- private logPrefix = (): string => {
- return logPrefix(` ${this.objName} | Performance statistics`);
- };
+ private readonly logPrefix = (): string => {
+ return logPrefix(` ${this.objName} | Performance statistics`)
+ }
}
-export { PerformanceStatistics } from './PerformanceStatistics.js';
-export { type Storage } from './storage/Storage.js';
-export { StorageFactory } from './storage/StorageFactory.js';
+export { PerformanceStatistics } from './PerformanceStatistics.js'
+export { type Storage } from './storage/Storage.js'
+export { StorageFactory } from './storage/StorageFactory.js'
// Copyright Jerome Benoit. 2021-2023. All Rights Reserved.
-import { closeSync, existsSync, mkdirSync, openSync, writeSync } from 'node:fs';
-import { dirname } from 'node:path';
+import { closeSync, existsSync, mkdirSync, openSync, writeSync } from 'node:fs'
+import { dirname } from 'node:path'
-import { Storage } from './Storage.js';
-import { BaseError } from '../../exception/index.js';
-import { FileType, type Statistics } from '../../types/index.js';
+import { Storage } from './Storage.js'
+import { BaseError } from '../../exception/index.js'
+import { FileType, type Statistics } from '../../types/index.js'
import {
AsyncLock,
AsyncLockType,
JSONStringifyWithMapSupport,
- handleFileException,
- isNullOrUndefined,
-} from '../../utils/index.js';
+ handleFileException
+} from '../../utils/index.js'
export class JsonFileStorage extends Storage {
- private static performanceRecords: Map<string, Statistics>;
+ private static performanceRecords: Map<string, Statistics>
- private fd?: number;
+ private fd?: number
- constructor(storageUri: string, logPrefix: string) {
- super(storageUri, logPrefix);
- this.dbName = this.storageUri.pathname;
+ constructor (storageUri: string, logPrefix: string) {
+ super(storageUri, logPrefix)
+ this.dbName = this.storageUri.pathname
}
- public storePerformanceStatistics(performanceStatistics: Statistics): void {
- this.checkPerformanceRecordsFile();
- JsonFileStorage.performanceRecords.set(performanceStatistics.id, performanceStatistics);
+ public storePerformanceStatistics (performanceStatistics: Statistics): void {
+ this.checkPerformanceRecordsFile()
+ JsonFileStorage.performanceRecords.set(performanceStatistics.id, performanceStatistics)
AsyncLock.runExclusive(AsyncLockType.performance, () => {
writeSync(
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.fd!,
JSONStringifyWithMapSupport([...JsonFileStorage.performanceRecords.values()], 2),
0,
- 'utf8',
- );
+ 'utf8'
+ )
}).catch((error) => {
handleFileException(
this.dbName,
FileType.PerformanceRecords,
error as NodeJS.ErrnoException,
- this.logPrefix,
- );
- });
+ this.logPrefix
+ )
+ })
}
- public open(): void {
- JsonFileStorage.performanceRecords = new Map<string, Statistics>();
+ public open (): void {
+ JsonFileStorage.performanceRecords = new Map<string, Statistics>()
try {
- if (isNullOrUndefined(this?.fd)) {
+ if (this?.fd == null) {
if (!existsSync(dirname(this.dbName))) {
- mkdirSync(dirname(this.dbName), { recursive: true });
+ mkdirSync(dirname(this.dbName), { recursive: true })
}
- this.fd = openSync(this.dbName, 'w');
+ this.fd = openSync(this.dbName, 'w')
}
} catch (error) {
handleFileException(
this.dbName,
FileType.PerformanceRecords,
error as NodeJS.ErrnoException,
- this.logPrefix,
- );
+ this.logPrefix
+ )
}
}
- public close(): void {
- JsonFileStorage.performanceRecords.clear();
+ public close (): void {
+ JsonFileStorage.performanceRecords.clear()
try {
- if (this?.fd) {
- closeSync(this.fd);
- delete this?.fd;
+ if (this?.fd != null) {
+ closeSync(this.fd)
+ delete this?.fd
}
} catch (error) {
handleFileException(
this.dbName,
FileType.PerformanceRecords,
error as NodeJS.ErrnoException,
- this.logPrefix,
- );
+ this.logPrefix
+ )
}
}
- private checkPerformanceRecordsFile(): void {
- if (!this?.fd) {
+ private checkPerformanceRecordsFile (): void {
+ if (this?.fd == null) {
throw new BaseError(
- `${this.logPrefix} Performance records '${this.dbName}' file descriptor not found`,
- );
+ `${this.logPrefix} Performance records '${this.dbName}' file descriptor not found`
+ )
}
}
}
// Copyright Jerome Benoit. 2021-2023. All Rights Reserved.
import {
- Configuration,
- Connection,
+ type Configuration,
+ type Connection,
type IDatabaseDriver,
MikroORM,
- type Options,
-} from '@mikro-orm/core';
-import { TsMorphMetadataProvider } from '@mikro-orm/reflection';
+ type Options
+} from '@mikro-orm/core'
+import { TsMorphMetadataProvider } from '@mikro-orm/reflection'
-import { Storage } from './Storage.js';
+import { Storage } from './Storage.js'
import {
type MikroOrmDbType,
PerformanceData,
PerformanceRecord,
type Statistics,
- StorageType,
-} from '../../types/index.js';
-import { Constants } from '../../utils/index.js';
+ StorageType
+} from '../../types/index.js'
+import { Constants } from '../../utils/index.js'
export class MikroOrmStorage extends Storage {
- private storageType: StorageType;
- private orm?: MikroORM;
+ private readonly storageType: StorageType
+ private orm?: MikroORM
- constructor(storageUri: string, logPrefix: string, storageType: StorageType) {
- super(storageUri, logPrefix);
- this.storageType = storageType;
- this.dbName = this.getDBName();
+ constructor (storageUri: string, logPrefix: string, storageType: StorageType) {
+ super(storageUri, logPrefix)
+ this.storageType = storageType
+ this.dbName = this.getDBName()
}
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
- public async storePerformanceStatistics(performanceStatistics: Statistics): Promise<void> {
+ public async storePerformanceStatistics (performanceStatistics: Statistics): Promise<void> {
try {
- const performanceRecord = new PerformanceRecord();
- await this.orm?.em.persistAndFlush(performanceRecord);
+ const performanceRecord = new PerformanceRecord()
+ await this.orm?.em.persistAndFlush(performanceRecord)
} catch (error) {
- this.handleDBError(this.storageType, error as Error, Constants.PERFORMANCE_RECORDS_TABLE);
+ this.handleDBError(this.storageType, error as Error, Constants.PERFORMANCE_RECORDS_TABLE)
}
}
- public async open(): Promise<void> {
+ public async open (): Promise<void> {
try {
- if (!this?.orm) {
- this.orm = await MikroORM.init(this.getOptions(), true);
+ if (this?.orm == null) {
+ this.orm = await MikroORM.init(this.getOptions(), true)
}
} catch (error) {
- this.handleDBError(this.storageType, error as Error);
+ this.handleDBError(this.storageType, error as Error)
}
}
- public async close(): Promise<void> {
+ public async close (): Promise<void> {
try {
- if (this?.orm) {
- await this.orm.close();
- delete this?.orm;
+ if (this?.orm != null) {
+ await this.orm.close()
+ delete this?.orm
}
} catch (error) {
- this.handleDBError(this.storageType, error as Error);
+ this.handleDBError(this.storageType, error as Error)
}
}
- private getDBName(): string {
+ private getDBName (): string {
if (this.storageType === StorageType.SQLITE) {
- return `${Constants.DEFAULT_PERFORMANCE_RECORDS_DB_NAME}.db`;
+ return `${Constants.DEFAULT_PERFORMANCE_RECORDS_DB_NAME}.db`
}
return (
this.storageUri.pathname.replace(/(?:^\/)|(?:\/$)/g, '') ??
Constants.DEFAULT_PERFORMANCE_RECORDS_DB_NAME
- );
+ )
}
- private getOptions():
- | Configuration<IDatabaseDriver<Connection>>
- | Options<IDatabaseDriver<Connection>> {
+ private getOptions ():
+ | Configuration<IDatabaseDriver<Connection>>
+ | Options<IDatabaseDriver<Connection>> {
return {
metadataProvider: TsMorphMetadataProvider,
entities: [PerformanceRecord, PerformanceData],
type: this.storageType as MikroOrmDbType,
- clientUrl: this.getClientUrl(),
- };
+ clientUrl: this.getClientUrl()
+ }
}
- private getClientUrl(): string | undefined {
+ private getClientUrl (): string | undefined {
switch (this.storageType) {
case StorageType.SQLITE:
case StorageType.MARIA_DB:
case StorageType.MYSQL:
- return this.storageUri.toString();
+ return this.storageUri.toString()
}
}
}
// Copyright Jerome Benoit. 2021-2023. All Rights Reserved.
-import { MongoClient } from 'mongodb';
+import { MongoClient } from 'mongodb'
-import { Storage } from './Storage.js';
-import { BaseError } from '../../exception/index.js';
-import { type Statistics, StorageType } from '../../types/index.js';
-import { Constants } from '../../utils/index.js';
+import { Storage } from './Storage.js'
+import { BaseError } from '../../exception/index.js'
+import { type Statistics, StorageType } from '../../types/index.js'
+import { Constants } from '../../utils/index.js'
export class MongoDBStorage extends Storage {
- private readonly client?: MongoClient;
- private connected: boolean;
+ private readonly client?: MongoClient
+ private connected: boolean
- constructor(storageUri: string, logPrefix: string) {
- super(storageUri, logPrefix);
- this.client = new MongoClient(this.storageUri.toString());
- this.connected = false;
+ constructor (storageUri: string, logPrefix: string) {
+ super(storageUri, logPrefix)
+ this.client = new MongoClient(this.storageUri.toString())
+ this.connected = false
this.dbName =
this.storageUri.pathname.replace(/(?:^\/)|(?:\/$)/g, '') ??
- Constants.DEFAULT_PERFORMANCE_RECORDS_DB_NAME;
+ Constants.DEFAULT_PERFORMANCE_RECORDS_DB_NAME
}
- public async storePerformanceStatistics(performanceStatistics: Statistics): Promise<void> {
+ public async storePerformanceStatistics (performanceStatistics: Statistics): Promise<void> {
try {
- this.checkDBConnection();
+ this.checkDBConnection()
await this.client
?.db(this.dbName)
.collection<Statistics>(Constants.PERFORMANCE_RECORDS_TABLE)
- .replaceOne({ id: performanceStatistics.id }, performanceStatistics, { upsert: true });
+ .replaceOne({ id: performanceStatistics.id }, performanceStatistics, { upsert: true })
} catch (error) {
- this.handleDBError(StorageType.MONGO_DB, error as Error, Constants.PERFORMANCE_RECORDS_TABLE);
+ this.handleDBError(StorageType.MONGO_DB, error as Error, Constants.PERFORMANCE_RECORDS_TABLE)
}
}
- public async open(): Promise<void> {
+ public async open (): Promise<void> {
try {
- if (!this.connected && this?.client) {
- await this.client.connect();
- this.connected = true;
+ if (!this.connected && this?.client != null) {
+ await this.client.connect()
+ this.connected = true
}
} catch (error) {
- this.handleDBError(StorageType.MONGO_DB, error as Error);
+ this.handleDBError(StorageType.MONGO_DB, error as Error)
}
}
- public async close(): Promise<void> {
+ public async close (): Promise<void> {
try {
- if (this.connected && this?.client) {
- await this.client.close();
- this.connected = false;
+ if (this.connected && this?.client != null) {
+ await this.client.close()
+ this.connected = false
}
} catch (error) {
- this.handleDBError(StorageType.MONGO_DB, error as Error);
+ this.handleDBError(StorageType.MONGO_DB, error as Error)
}
}
- private checkDBConnection() {
- if (!this?.client) {
+ private checkDBConnection (): void {
+ if (this?.client == null) {
throw new BaseError(
`${this.logPrefix} ${this.getDBNameFromStorageType(
- StorageType.MONGO_DB,
- )} client initialization failed while trying to issue a request`,
- );
+ StorageType.MONGO_DB
+ )} client initialization failed while trying to issue a request`
+ )
}
if (!this.connected) {
throw new BaseError(
`${this.logPrefix} ${this.getDBNameFromStorageType(
- StorageType.MONGO_DB,
- )} connection not opened while trying to issue a request`,
- );
+ StorageType.MONGO_DB
+ )} connection not opened while trying to issue a request`
+ )
}
}
}
// Copyright Jerome Benoit. 2021-2023. All Rights Reserved.
-import { URL } from 'node:url';
+import { URL } from 'node:url'
import {
DBName,
type EmptyObject,
type HandleErrorParams,
type Statistics,
- StorageType,
-} from '../../types/index.js';
-import { isNullOrUndefined, logger, setDefaultErrorParams } from '../../utils/index.js';
+ StorageType
+} from '../../types/index.js'
+import { logger, setDefaultErrorParams } from '../../utils/index.js'
export abstract class Storage {
- protected readonly storageUri: URL;
- protected readonly logPrefix: string;
- protected dbName!: string;
+ protected readonly storageUri: URL
+ protected readonly logPrefix: string
+ protected dbName!: string
- constructor(storageUri: string, logPrefix: string) {
- this.storageUri = new URL(storageUri);
- this.logPrefix = logPrefix;
+ constructor (storageUri: string, logPrefix: string) {
+ this.storageUri = new URL(storageUri)
+ this.logPrefix = logPrefix
}
- protected handleDBError(
+ protected handleDBError (
type: StorageType,
error: Error,
table?: string,
- params: HandleErrorParams<EmptyObject> = { throwError: false, consoleOut: false },
+ params: HandleErrorParams<EmptyObject> = { throwError: false, consoleOut: false }
): void {
- setDefaultErrorParams(params, { throwError: false, consoleOut: false });
- const inTableOrCollectionStr =
- (!isNullOrUndefined(table) || !table) && ` in table or collection '${table}'`;
+ setDefaultErrorParams(params, { throwError: false, consoleOut: false })
+ const inTableOrCollectionStr = table != null && ` in table or collection '${table}'`
logger.error(
`${this.logPrefix} ${this.getDBNameFromStorageType(type)} error '${
error.message
}'${inTableOrCollectionStr}:`,
- error,
- );
- if (params?.throwError) {
- throw error;
+ error
+ )
+ if (params?.throwError === true) {
+ throw error
}
}
- protected getDBNameFromStorageType(type: StorageType): DBName | undefined {
+ protected getDBNameFromStorageType (type: StorageType): DBName | undefined {
switch (type) {
case StorageType.MARIA_DB:
- return DBName.MARIA_DB;
+ return DBName.MARIA_DB
case StorageType.MONGO_DB:
- return DBName.MONGO_DB;
+ return DBName.MONGO_DB
case StorageType.MYSQL:
- return DBName.MYSQL;
+ return DBName.MYSQL
case StorageType.SQLITE:
- return DBName.SQLITE;
+ return DBName.SQLITE
}
}
- public abstract open(): void | Promise<void>;
- public abstract close(): void | Promise<void>;
- public abstract storePerformanceStatistics(
- performanceStatistics: Statistics,
- ): void | Promise<void>;
+ public abstract open (): void | Promise<void>
+ public abstract close (): void | Promise<void>
+ public abstract storePerformanceStatistics (
+ performanceStatistics: Statistics
+ ): void | Promise<void>
}
// Copyright Jerome Benoit. 2021-2023. All Rights Reserved.
-import { JsonFileStorage } from './JsonFileStorage.js';
+import { JsonFileStorage } from './JsonFileStorage.js'
// eslint-disable-next-line @typescript-eslint/no-unused-vars
-import { MikroOrmStorage } from './MikroOrmStorage.js';
-import { MongoDBStorage } from './MongoDBStorage.js';
-import type { Storage } from './Storage.js';
-import { BaseError } from '../../exception/index.js';
-import { StorageType } from '../../types/index.js';
+import { MikroOrmStorage } from './MikroOrmStorage.js'
+import { MongoDBStorage } from './MongoDBStorage.js'
+import type { Storage } from './Storage.js'
+import { BaseError } from '../../exception/index.js'
+import { StorageType } from '../../types/index.js'
+// eslint-disable-next-line @typescript-eslint/no-extraneous-class
export class StorageFactory {
- private constructor() {
+ private constructor () {
// This is intentional
}
- public static getStorage(
+ public static getStorage (
type: StorageType,
connectionUri: string,
- logPrefix: string,
+ logPrefix: string
): Storage | undefined {
- let storageInstance: Storage;
+ let storageInstance: Storage
switch (type) {
case StorageType.JSON_FILE:
- storageInstance = new JsonFileStorage(connectionUri, logPrefix);
- break;
+ storageInstance = new JsonFileStorage(connectionUri, logPrefix)
+ break
case StorageType.MONGO_DB:
- storageInstance = new MongoDBStorage(connectionUri, logPrefix);
- break;
+ storageInstance = new MongoDBStorage(connectionUri, logPrefix)
+ break
// case StorageType.MYSQL:
// case StorageType.MARIA_DB:
// case StorageType.SQLITE:
- // storageInstance = new MikroOrmStorage(connectionUri, logPrefix, type);
- // break;
+ // storageInstance = new MikroOrmStorage(connectionUri, logPrefix, type)
+ // break
default:
- throw new BaseError(`${logPrefix} Unknown storage type: ${type}`);
+ throw new BaseError(`${logPrefix} Unknown storage type: ${type}`)
}
- return storageInstance;
+ return storageInstance
}
}
#!/usr/bin/env node
-const fs = require('node:fs');
+const fs = require('node:fs')
-const { MongoClient } = require('mongodb');
+const { MongoClient } = require('mongodb')
// This script deletes charging stations
// Filter charging stations by id pattern
// Delete these charging stations all at once
// Config
-const config = JSON.parse(fs.readFileSync('scriptConfig.json', 'utf8'));
+const config = JSON.parse(fs.readFileSync('scriptConfig.json', 'utf8'))
// Mongo Connection and Query
if (config?.mongoConnectionString) {
- MongoClient.connect(config.mongoConnectionString, async function (err, client) {
- const db = client.db();
+ // eslint-disable-next-line n/handle-callback-err
+ MongoClient.connect(config.mongoConnectionString, async function (_err, client) {
+ const db = client.db()
for await (const tenantID of config.tenantIDs) {
const response = await db
.collection(`${tenantID}.chargingstations`)
- .deleteMany({ _id: { $regex: config.idPattern } });
+ .deleteMany({ _id: { $regex: config.idPattern } })
console.info(
response.deletedCount,
`Charging Stations with id = %${config.idPattern}% deleted. TenantID =`,
- tenantID,
- );
+ tenantID
+ )
}
- client.close();
- });
+ client.close()
+ })
}
#!/usr/bin/env node
-const fs = require('node:fs');
+const fs = require('node:fs')
-const { MongoClient } = require('mongodb');
+const { MongoClient } = require('mongodb')
// This script sets charging stations public or private
// Filter charging stations by id pattern
// set public = true
// Config
-const config = JSON.parse(fs.readFileSync('scriptConfig.json', 'utf8'));
+const config = JSON.parse(fs.readFileSync('scriptConfig.json', 'utf8'))
// Mongo Connection and Query
if (config?.mongoConnectionString) {
- MongoClient.connect(config.mongoConnectionString, async function (err, client) {
- const db = client.db();
+ // eslint-disable-next-line n/handle-callback-err
+ MongoClient.connect(config.mongoConnectionString, async function (_err, client) {
+ const db = client.db()
for await (const tenantID of config.tenantIDs) {
const response = await db
.collection(`${tenantID}.chargingstations`)
- .updateMany({ _id: { $regex: config.idPattern } }, { $set: { public: config.publicFlag } });
+ .updateMany({ _id: { $regex: config.idPattern } }, { $set: { public: config.publicFlag } })
console.info(
response.modifiedCount,
`Charging Stations with id = %${config.idPattern}% updated. TenantID =`,
- tenantID,
- );
+ tenantID
+ )
}
- client.close();
- });
+ client.close()
+ })
}
// Partial Copyright Jerome Benoit. 2021-2023. All Rights Reserved.
-import chalk from 'chalk';
+import chalk from 'chalk'
-import { Bootstrap } from './charging-station/index.js';
+import { Bootstrap } from './charging-station/index.js'
try {
- await Bootstrap.getInstance().start();
+ await Bootstrap.getInstance().start()
} catch (error) {
- console.error(chalk.red('Startup error: '), error);
+ console.error(chalk.red('Startup error: '), error)
}
export enum IdTagDistribution {
RANDOM = 'random',
ROUND_ROBIN = 'round-robin',
- CONNECTOR_AFFINITY = 'connector-affinity',
+ CONNECTOR_AFFINITY = 'connector-affinity'
}
export interface AutomaticTransactionGeneratorConfiguration {
- enable: boolean;
- minDuration: number;
- maxDuration: number;
- minDelayBetweenTwoTransactions: number;
- maxDelayBetweenTwoTransactions: number;
- probabilityOfStart: number;
- stopAfterHours: number;
- stopOnConnectionFailure: boolean;
- requireAuthorize?: boolean;
- idTagDistribution?: IdTagDistribution;
+ enable: boolean
+ minDuration: number
+ maxDuration: number
+ minDelayBetweenTwoTransactions: number
+ maxDelayBetweenTwoTransactions: number
+ probabilityOfStart: number
+ stopAfterHours: number
+ stopOnConnectionFailure: boolean
+ requireAuthorize?: boolean
+ idTagDistribution?: IdTagDistribution
}
export interface Status {
- start: boolean;
- startDate?: Date;
- lastRunDate?: Date;
- stopDate?: Date;
- stoppedDate?: Date;
- authorizeRequests?: number;
- acceptedAuthorizeRequests?: number;
- rejectedAuthorizeRequests?: number;
- startTransactionRequests?: number;
- acceptedStartTransactionRequests?: number;
- rejectedStartTransactionRequests?: number;
- stopTransactionRequests?: number;
- acceptedStopTransactionRequests?: number;
- rejectedStopTransactionRequests?: number;
- skippedConsecutiveTransactions?: number;
- skippedTransactions?: number;
+ start: boolean
+ startDate?: Date
+ lastRunDate?: Date
+ stopDate?: Date
+ stoppedDate?: Date
+ authorizeRequests?: number
+ acceptedAuthorizeRequests?: number
+ rejectedAuthorizeRequests?: number
+ startTransactionRequests?: number
+ acceptedStartTransactionRequests?: number
+ rejectedStartTransactionRequests?: number
+ stopTransactionRequests?: number
+ acceptedStopTransactionRequests?: number
+ rejectedStopTransactionRequests?: number
+ skippedConsecutiveTransactions?: number
+ skippedTransactions?: number
}
export interface ChargingStationAutomaticTransactionGeneratorConfiguration {
- automaticTransactionGenerator?: AutomaticTransactionGeneratorConfiguration;
- automaticTransactionGeneratorStatuses?: Status[];
+ automaticTransactionGenerator?: AutomaticTransactionGeneratorConfiguration
+ automaticTransactionGeneratorStatuses?: Status[]
}
-import type { ChargingStationAutomaticTransactionGeneratorConfiguration } from './AutomaticTransactionGenerator.js';
-import type { ChargingStationInfoConfiguration } from './ChargingStationInfo.js';
-import type { ChargingStationOcppConfiguration } from './ChargingStationOcppConfiguration.js';
-import type { ConnectorStatus } from './ConnectorStatus.js';
-import type { EvseStatus } from './Evse.js';
+import type { ChargingStationAutomaticTransactionGeneratorConfiguration } from './AutomaticTransactionGenerator.js'
+import type { ChargingStationInfoConfiguration } from './ChargingStationInfo.js'
+import type { ChargingStationOcppConfiguration } from './ChargingStationOcppConfiguration.js'
+import type { ConnectorStatus } from './ConnectorStatus.js'
+import type { EvseStatus } from './Evse.js'
interface ConnectorsConfiguration {
- connectorsStatus?: ConnectorStatus[];
+ connectorsStatus?: ConnectorStatus[]
}
export type EvseStatusConfiguration = Omit<EvseStatus, 'connectors'> & {
- connectorsStatus?: ConnectorStatus[];
-};
+ connectorsStatus?: ConnectorStatus[]
+}
interface EvsesConfiguration {
- evsesStatus?: EvseStatusConfiguration[];
+ evsesStatus?: EvseStatusConfiguration[]
}
export type ChargingStationConfiguration = ChargingStationInfoConfiguration &
- ChargingStationOcppConfiguration &
- ChargingStationAutomaticTransactionGeneratorConfiguration &
- ConnectorsConfiguration &
- EvsesConfiguration & {
- configurationHash?: string;
- };
+ChargingStationOcppConfiguration &
+ChargingStationAutomaticTransactionGeneratorConfiguration &
+ConnectorsConfiguration &
+EvsesConfiguration & {
+ configurationHash?: string
+}
registered = 'registered',
accepted = 'accepted',
updated = 'updated',
- connectorStatusChanged = 'connectorStatusChanged',
+ connectorStatusChanged = 'connectorStatusChanged'
}
-import type { ChargingStationTemplate } from './ChargingStationTemplate.js';
-import type { FirmwareStatus } from './ocpp/Requests.js';
+import type { ChargingStationTemplate } from './ChargingStationTemplate.js'
+import type { FirmwareStatus } from './ocpp/Requests.js'
export type ChargingStationInfo = Omit<
- ChargingStationTemplate,
- | 'AutomaticTransactionGenerator'
- | 'Configuration'
- | 'Connectors'
- | 'Evses'
- | 'power'
- | 'powerUnit'
- | 'chargeBoxSerialNumberPrefix'
- | 'chargePointSerialNumberPrefix'
- | 'meterSerialNumberPrefix'
+ChargingStationTemplate,
+| 'AutomaticTransactionGenerator'
+| 'Configuration'
+| 'Connectors'
+| 'Evses'
+| 'power'
+| 'powerUnit'
+| 'chargeBoxSerialNumberPrefix'
+| 'chargePointSerialNumberPrefix'
+| 'meterSerialNumberPrefix'
> & {
- hashId: string;
+ hashId: string
/** @deprecated Use hashId instead */
- infoHash?: string;
- chargingStationId?: string;
- chargeBoxSerialNumber?: string;
- chargePointSerialNumber?: string;
- meterSerialNumber?: string;
- maximumPower?: number; // Always in Watt
- maximumAmperage?: number; // Always in Ampere
- firmwareStatus?: FirmwareStatus;
-};
+ infoHash?: string
+ chargingStationId?: string
+ chargeBoxSerialNumber?: string
+ chargePointSerialNumber?: string
+ meterSerialNumber?: string
+ maximumPower?: number // Always in Watt
+ maximumAmperage?: number // Always in Ampere
+ firmwareStatus?: FirmwareStatus
+}
export interface ChargingStationInfoConfiguration {
- stationInfo?: ChargingStationInfo;
+ stationInfo?: ChargingStationInfo
}
-import type { OCPPConfigurationKey } from './ocpp/Configuration.js';
+import type { OCPPConfigurationKey } from './ocpp/Configuration.js'
export type ConfigurationKey = OCPPConfigurationKey & {
- visible?: boolean;
- reboot?: boolean;
-};
+ visible?: boolean
+ reboot?: boolean
+}
export interface ChargingStationOcppConfiguration {
- configurationKey?: ConfigurationKey[];
+ configurationKey?: ConfigurationKey[]
}
-import type { ClientRequestArgs } from 'node:http';
+import type { ClientRequestArgs } from 'node:http'
-import type { ClientOptions } from 'ws';
+import type { ClientOptions } from 'ws'
-import type { AutomaticTransactionGeneratorConfiguration } from './AutomaticTransactionGenerator.js';
-import type { ChargingStationOcppConfiguration } from './ChargingStationOcppConfiguration.js';
-import type { ConnectorStatus } from './ConnectorStatus.js';
-import type { EvseTemplate } from './Evse.js';
-import type { OCPPProtocol } from './ocpp/OCPPProtocol.js';
-import type { OCPPVersion } from './ocpp/OCPPVersion.js';
+import type { AutomaticTransactionGeneratorConfiguration } from './AutomaticTransactionGenerator.js'
+import type { ChargingStationOcppConfiguration } from './ChargingStationOcppConfiguration.js'
+import type { ConnectorStatus } from './ConnectorStatus.js'
+import type { EvseTemplate } from './Evse.js'
+import type { OCPPProtocol } from './ocpp/OCPPProtocol.js'
+import type { OCPPVersion } from './ocpp/OCPPVersion.js'
import type {
FirmwareStatus,
IncomingRequestCommand,
MessageTrigger,
- RequestCommand,
-} from './ocpp/Requests.js';
+ RequestCommand
+} from './ocpp/Requests.js'
export enum CurrentType {
AC = 'AC',
- DC = 'DC',
+ DC = 'DC'
}
export enum PowerUnits {
WATT = 'W',
- KILO_WATT = 'kW',
+ KILO_WATT = 'kW'
}
export enum AmpereUnits {
MILLI_AMPERE = 'mA',
CENTI_AMPERE = 'cA',
DECI_AMPERE = 'dA',
- AMPERE = 'A',
+ AMPERE = 'A'
}
export enum Voltage {
VOLTAGE_110 = 110,
VOLTAGE_230 = 230,
VOLTAGE_400 = 400,
- VOLTAGE_800 = 800,
+ VOLTAGE_800 = 800
}
-export type WsOptions = ClientOptions & ClientRequestArgs;
+export type WsOptions = ClientOptions & ClientRequestArgs
export interface FirmwareUpgrade {
versionUpgrade?: {
- patternGroup?: number;
- step?: number;
- };
- reset?: boolean;
- failureStatus?: FirmwareStatus;
+ patternGroup?: number
+ step?: number
+ }
+ reset?: boolean
+ failureStatus?: FirmwareStatus
}
interface CommandsSupport {
- incomingCommands: Record<IncomingRequestCommand, boolean>;
- outgoingCommands?: Record<RequestCommand, boolean>;
+ incomingCommands: Record<IncomingRequestCommand, boolean>
+ outgoingCommands?: Record<RequestCommand, boolean>
}
enum x509CertificateType {
CSMSRootCertificate = 'CSMSRootCertificate',
ManufacturerRootCertificate = 'ManufacturerRootCertificate',
ChargingStationCertificate = 'ChargingStationCertificate',
- V2GCertificate = 'V2GCertificate',
+ V2GCertificate = 'V2GCertificate'
}
export interface ChargingStationTemplate {
- templateHash?: string;
- supervisionUrls?: string | string[];
- supervisionUrlOcppConfiguration?: boolean;
- supervisionUrlOcppKey?: string;
- supervisionUser?: string;
- supervisionPassword?: string;
- ocppVersion?: OCPPVersion;
- ocppProtocol?: OCPPProtocol;
- ocppStrictCompliance?: boolean;
- ocppPersistentConfiguration?: boolean;
- stationInfoPersistentConfiguration?: boolean;
- automaticTransactionGeneratorPersistentConfiguration?: boolean;
- wsOptions?: WsOptions;
- idTagsFile?: string;
- baseName: string;
- nameSuffix?: string;
- fixedName?: boolean;
- chargePointModel: string;
- chargePointVendor: string;
- chargePointSerialNumberPrefix?: string;
- chargeBoxSerialNumberPrefix?: string;
- firmwareVersionPattern?: string;
- firmwareVersion?: string;
- firmwareUpgrade?: FirmwareUpgrade;
- iccid?: string;
- imsi?: string;
- meterSerialNumberPrefix?: string;
- meterType?: string;
- power?: number | number[];
- powerUnit?: PowerUnits;
- powerSharedByConnectors?: boolean;
- currentOutType?: CurrentType;
- voltageOut?: Voltage;
- numberOfPhases?: number;
- numberOfConnectors?: number | number[];
- useConnectorId0?: boolean;
- randomConnectors?: boolean;
- resetTime?: number;
- autoRegister?: boolean;
- autoReconnectMaxRetries?: number;
- reconnectExponentialDelay?: boolean;
- registrationMaxRetries?: number;
- enableStatistics?: boolean;
- remoteAuthorization?: boolean;
+ templateHash?: string
+ supervisionUrls?: string | string[]
+ supervisionUrlOcppConfiguration?: boolean
+ supervisionUrlOcppKey?: string
+ supervisionUser?: string
+ supervisionPassword?: string
+ ocppVersion?: OCPPVersion
+ ocppProtocol?: OCPPProtocol
+ ocppStrictCompliance?: boolean
+ ocppPersistentConfiguration?: boolean
+ stationInfoPersistentConfiguration?: boolean
+ automaticTransactionGeneratorPersistentConfiguration?: boolean
+ wsOptions?: WsOptions
+ idTagsFile?: string
+ baseName: string
+ nameSuffix?: string
+ fixedName?: boolean
+ chargePointModel: string
+ chargePointVendor: string
+ chargePointSerialNumberPrefix?: string
+ chargeBoxSerialNumberPrefix?: string
+ firmwareVersionPattern?: string
+ firmwareVersion?: string
+ firmwareUpgrade?: FirmwareUpgrade
+ iccid?: string
+ imsi?: string
+ meterSerialNumberPrefix?: string
+ meterType?: string
+ power?: number | number[]
+ powerUnit?: PowerUnits
+ powerSharedByConnectors?: boolean
+ currentOutType?: CurrentType
+ voltageOut?: Voltage
+ numberOfPhases?: number
+ numberOfConnectors?: number | number[]
+ useConnectorId0?: boolean
+ randomConnectors?: boolean
+ resetTime?: number
+ autoRegister?: boolean
+ autoReconnectMaxRetries?: number
+ reconnectExponentialDelay?: boolean
+ registrationMaxRetries?: number
+ enableStatistics?: boolean
+ remoteAuthorization?: boolean
/** @deprecated Replaced by remoteAuthorization */
- mustAuthorizeAtRemoteStart?: boolean;
+ mustAuthorizeAtRemoteStart?: boolean
/** @deprecated Replaced by ocppStrictCompliance */
- payloadSchemaValidation?: boolean;
- amperageLimitationOcppKey?: string;
- amperageLimitationUnit?: AmpereUnits;
- beginEndMeterValues?: boolean;
- outOfOrderEndMeterValues?: boolean;
- meteringPerTransaction?: boolean;
- transactionDataMeterValues?: boolean;
- stopTransactionsOnStopped?: boolean;
- mainVoltageMeterValues?: boolean;
- phaseLineToLineVoltageMeterValues?: boolean;
- customValueLimitationMeterValues?: boolean;
- commandsSupport?: CommandsSupport;
- messageTriggerSupport?: Record<MessageTrigger, boolean>;
- Configuration?: ChargingStationOcppConfiguration;
- AutomaticTransactionGenerator?: AutomaticTransactionGeneratorConfiguration;
- Evses?: Record<string, EvseTemplate>;
- Connectors?: Record<string, ConnectorStatus>;
- x509Certificates?: Record<x509CertificateType, string>;
+ payloadSchemaValidation?: boolean
+ amperageLimitationOcppKey?: string
+ amperageLimitationUnit?: AmpereUnits
+ beginEndMeterValues?: boolean
+ outOfOrderEndMeterValues?: boolean
+ meteringPerTransaction?: boolean
+ transactionDataMeterValues?: boolean
+ stopTransactionsOnStopped?: boolean
+ mainVoltageMeterValues?: boolean
+ phaseLineToLineVoltageMeterValues?: boolean
+ customValueLimitationMeterValues?: boolean
+ commandsSupport?: CommandsSupport
+ messageTriggerSupport?: Record<MessageTrigger, boolean>
+ Configuration?: ChargingStationOcppConfiguration
+ AutomaticTransactionGenerator?: AutomaticTransactionGeneratorConfiguration
+ Evses?: Record<string, EvseTemplate>
+ Connectors?: Record<string, ConnectorStatus>
+ x509Certificates?: Record<x509CertificateType, string>
}
-import type { WebSocket } from 'ws';
+import type { WebSocket } from 'ws'
-import type { ChargingStationAutomaticTransactionGeneratorConfiguration } from './AutomaticTransactionGenerator.js';
-import { ChargingStationEvents } from './ChargingStationEvents.js';
-import type { ChargingStationInfo } from './ChargingStationInfo.js';
-import type { ChargingStationOcppConfiguration } from './ChargingStationOcppConfiguration.js';
-import type { ConnectorStatus } from './ConnectorStatus.js';
-import type { EvseStatus } from './Evse.js';
-import type { JsonObject } from './JsonType.js';
-import type { BootNotificationResponse } from './ocpp/Responses.js';
-import type { Statistics } from './Statistics.js';
-import { type WorkerData, type WorkerMessage, WorkerMessageEvents } from '../worker/index.js';
+import type { ChargingStationAutomaticTransactionGeneratorConfiguration } from './AutomaticTransactionGenerator.js'
+import { ChargingStationEvents } from './ChargingStationEvents.js'
+import type { ChargingStationInfo } from './ChargingStationInfo.js'
+import type { ChargingStationOcppConfiguration } from './ChargingStationOcppConfiguration.js'
+import type { ConnectorStatus } from './ConnectorStatus.js'
+import type { EvseStatus } from './Evse.js'
+import type { JsonObject } from './JsonType.js'
+import type { BootNotificationResponse } from './ocpp/Responses.js'
+import type { Statistics } from './Statistics.js'
+import { type WorkerData, type WorkerMessage, WorkerMessageEvents } from '../worker/index.js'
interface ChargingStationWorkerOptions extends JsonObject {
- elementStartDelay?: number;
+ elementStartDelay?: number
}
export interface ChargingStationWorkerData extends WorkerData {
- index: number;
- templateFile: string;
- chargingStationWorkerOptions?: ChargingStationWorkerOptions;
+ index: number
+ templateFile: string
+ chargingStationWorkerOptions?: ChargingStationWorkerOptions
}
export type EvseStatusWorkerType = Omit<EvseStatus, 'connectors'> & {
- connectors?: ConnectorStatus[];
-};
+ connectors?: ConnectorStatus[]
+}
export interface ChargingStationData extends WorkerData {
- started: boolean;
- stationInfo: ChargingStationInfo;
- connectors: ConnectorStatus[];
- evses: EvseStatusWorkerType[];
- ocppConfiguration: ChargingStationOcppConfiguration;
+ started: boolean
+ stationInfo: ChargingStationInfo
+ connectors: ConnectorStatus[]
+ evses: EvseStatusWorkerType[]
+ ocppConfiguration: ChargingStationOcppConfiguration
wsState?:
- | typeof WebSocket.CONNECTING
- | typeof WebSocket.OPEN
- | typeof WebSocket.CLOSING
- | typeof WebSocket.CLOSED;
- bootNotificationResponse?: BootNotificationResponse;
- automaticTransactionGenerator?: ChargingStationAutomaticTransactionGeneratorConfiguration;
+ | typeof WebSocket.CONNECTING
+ | typeof WebSocket.OPEN
+ | typeof WebSocket.CLOSING
+ | typeof WebSocket.CLOSED
+ bootNotificationResponse?: BootNotificationResponse
+ automaticTransactionGenerator?: ChargingStationAutomaticTransactionGeneratorConfiguration
}
enum ChargingStationMessageEvents {
- performanceStatistics = 'performanceStatistics',
+ performanceStatistics = 'performanceStatistics'
}
export const ChargingStationWorkerMessageEvents = {
...WorkerMessageEvents,
...ChargingStationEvents,
- ...ChargingStationMessageEvents,
-} as const;
+ ...ChargingStationMessageEvents
+} as const
+// eslint-disable-next-line @typescript-eslint/no-redeclare
export type ChargingStationWorkerMessageEvents =
| WorkerMessageEvents
| ChargingStationEvents
- | ChargingStationMessageEvents;
+ | ChargingStationMessageEvents
-export type ChargingStationWorkerMessageData = ChargingStationData | Statistics;
+export type ChargingStationWorkerMessageData = ChargingStationData | Statistics
export type ChargingStationWorkerMessage<T extends ChargingStationWorkerMessageData> = Omit<
- WorkerMessage<T>,
- 'event'
+WorkerMessage<T>,
+'event'
> & {
- event: ChargingStationWorkerMessageEvents;
-};
+ event: ChargingStationWorkerMessageEvents
+}
-import type { ListenOptions } from 'node:net';
-import type { ResourceLimits } from 'node:worker_threads';
+import type { ListenOptions } from 'node:net'
+import type { ResourceLimits } from 'node:worker_threads'
-import type { WorkerChoiceStrategy } from 'poolifier';
+import type { WorkerChoiceStrategy } from 'poolifier'
-import type { StorageType } from './Storage.js';
-import type { ApplicationProtocol, AuthenticationType } from './UIProtocol.js';
-import type { WorkerProcessType } from '../worker/index.js';
+import type { StorageType } from './Storage.js'
+import type { ApplicationProtocol, AuthenticationType } from './UIProtocol.js'
+import type { WorkerProcessType } from '../worker/index.js'
-type ServerOptions = ListenOptions;
+type ServerOptions = ListenOptions
export enum ConfigurationSection {
log = 'log',
performanceStorage = 'performanceStorage',
worker = 'worker',
- uiServer = 'uiServer',
+ uiServer = 'uiServer'
}
export enum SupervisionUrlDistribution {
ROUND_ROBIN = 'round-robin',
RANDOM = 'random',
- CHARGING_STATION_AFFINITY = 'charging-station-affinity',
+ CHARGING_STATION_AFFINITY = 'charging-station-affinity'
}
export interface StationTemplateUrl {
- file: string;
- numberOfStations: number;
+ file: string
+ numberOfStations: number
}
export interface LogConfiguration {
- enabled?: boolean;
- file?: string;
- errorFile?: string;
- statisticsInterval?: number;
- level?: string;
- console?: boolean;
- format?: string;
- rotate?: boolean;
- maxFiles?: string | number;
- maxSize?: string | number;
+ enabled?: boolean
+ file?: string
+ errorFile?: string
+ statisticsInterval?: number
+ level?: string
+ console?: boolean
+ format?: string
+ rotate?: boolean
+ maxFiles?: string | number
+ maxSize?: string | number
}
export enum ApplicationProtocolVersion {
VERSION_11 = 1.1,
- VERSION_20 = 2.0,
+ VERSION_20 = 2.0
}
export interface UIServerConfiguration {
- enabled?: boolean;
- type?: ApplicationProtocol;
- version?: ApplicationProtocolVersion;
- options?: ServerOptions;
+ enabled?: boolean
+ type?: ApplicationProtocol
+ version?: ApplicationProtocolVersion
+ options?: ServerOptions
authentication?: {
- enabled: boolean;
- type: AuthenticationType;
- username?: string;
- password?: string;
- };
+ enabled: boolean
+ type: AuthenticationType
+ username?: string
+ password?: string
+ }
}
export interface StorageConfiguration {
- enabled?: boolean;
- type?: StorageType;
- uri?: string;
+ enabled?: boolean
+ type?: StorageType
+ uri?: string
}
-export type ElementsPerWorkerType = number | 'auto' | 'all';
+export type ElementsPerWorkerType = number | 'auto' | 'all'
export interface WorkerConfiguration {
- processType?: WorkerProcessType;
- startDelay?: number;
- elementsPerWorker?: ElementsPerWorkerType;
- elementStartDelay?: number;
- poolMinSize?: number;
- poolMaxSize?: number;
- resourceLimits?: ResourceLimits;
+ processType?: WorkerProcessType
+ startDelay?: number
+ elementsPerWorker?: ElementsPerWorkerType
+ elementStartDelay?: number
+ poolMinSize?: number
+ poolMaxSize?: number
+ resourceLimits?: ResourceLimits
}
export interface ConfigurationData {
- supervisionUrls?: string | string[];
- supervisionUrlDistribution?: SupervisionUrlDistribution;
- stationTemplateUrls: StationTemplateUrl[];
- log?: LogConfiguration;
- worker?: WorkerConfiguration;
- uiServer?: UIServerConfiguration;
- performanceStorage?: StorageConfiguration;
+ supervisionUrls?: string | string[]
+ supervisionUrlDistribution?: SupervisionUrlDistribution
+ stationTemplateUrls: StationTemplateUrl[]
+ log?: LogConfiguration
+ worker?: WorkerConfiguration
+ uiServer?: UIServerConfiguration
+ performanceStorage?: StorageConfiguration
/** @deprecated Moved to charging station template */
- autoReconnectMaxRetries?: number;
+ autoReconnectMaxRetries?: number
/** @deprecated Moved to worker configuration section. */
- workerProcess?: WorkerProcessType;
+ workerProcess?: WorkerProcessType
/** @deprecated Moved to worker configuration section. */
- workerStartDelay?: number;
+ workerStartDelay?: number
/** @deprecated Moved to worker configuration section. */
- elementStartDelay?: number;
+ elementStartDelay?: number
/** @deprecated Moved to worker configuration section. */
- workerPoolMinSize?: number;
+ workerPoolMinSize?: number
/** @deprecated Moved to worker configuration section. */
- workerPoolMaxSize?: number;
+ workerPoolMaxSize?: number
/** @deprecated Moved to worker configuration section. */
- workerPoolStrategy?: WorkerChoiceStrategy;
+ workerPoolStrategy?: WorkerChoiceStrategy
/** @deprecated Moved to worker configuration section. */
- chargingStationsPerWorker?: number;
+ chargingStationsPerWorker?: number
/** @deprecated Moved to log configuration section. */
- logStatisticsInterval?: number;
+ logStatisticsInterval?: number
/** @deprecated Moved to log configuration section. */
- logEnabled?: boolean;
+ logEnabled?: boolean
/** @deprecated Moved to log configuration section. */
- logConsole?: boolean;
+ logConsole?: boolean
/** @deprecated Moved to log configuration section. */
- logFormat?: string;
+ logFormat?: string
/** @deprecated Moved to log configuration section. */
- logLevel?: string;
+ logLevel?: string
/** @deprecated Moved to log configuration section. */
- logRotate?: boolean;
+ logRotate?: boolean
/** @deprecated Moved to log configuration section. */
- logMaxFiles?: number | string;
+ logMaxFiles?: number | string
/** @deprecated Moved to log configuration section. */
- logMaxSize?: number | string;
+ logMaxSize?: number | string
/** @deprecated Moved to log configuration section. */
- logFile?: string;
+ logFile?: string
/** @deprecated Moved to log configuration section. */
- logErrorFile?: string;
+ logErrorFile?: string
}
-import type { SampledValueTemplate } from './MeasurandPerPhaseSampledValueTemplates.js';
-import type { ChargingProfile } from './ocpp/ChargingProfile.js';
-import type { ConnectorStatusEnum } from './ocpp/ConnectorStatusEnum.js';
-import type { MeterValue } from './ocpp/MeterValues.js';
-import type { AvailabilityType } from './ocpp/Requests.js';
-import type { Reservation } from './ocpp/Reservation.js';
+import type { SampledValueTemplate } from './MeasurandPerPhaseSampledValueTemplates.js'
+import type { ChargingProfile } from './ocpp/ChargingProfile.js'
+import type { ConnectorStatusEnum } from './ocpp/ConnectorStatusEnum.js'
+import type { MeterValue } from './ocpp/MeterValues.js'
+import type { AvailabilityType } from './ocpp/Requests.js'
+import type { Reservation } from './ocpp/Reservation.js'
export interface ConnectorStatus {
- availability: AvailabilityType;
- bootStatus?: ConnectorStatusEnum;
- status?: ConnectorStatusEnum;
- MeterValues: SampledValueTemplate[];
- authorizeIdTag?: string;
- idTagAuthorized?: boolean;
- localAuthorizeIdTag?: string;
- idTagLocalAuthorized?: boolean;
- transactionRemoteStarted?: boolean;
- transactionStarted?: boolean;
- transactionStart?: Date;
- transactionId?: number;
- transactionSetInterval?: NodeJS.Timeout;
- transactionIdTag?: string;
- energyActiveImportRegisterValue?: number; // In Wh
- transactionEnergyActiveImportRegisterValue?: number; // In Wh
- transactionBeginMeterValue?: MeterValue;
- chargingProfiles?: ChargingProfile[];
- reservation?: Reservation;
+ availability: AvailabilityType
+ bootStatus?: ConnectorStatusEnum
+ status?: ConnectorStatusEnum
+ MeterValues: SampledValueTemplate[]
+ authorizeIdTag?: string
+ idTagAuthorized?: boolean
+ localAuthorizeIdTag?: string
+ idTagLocalAuthorized?: boolean
+ transactionRemoteStarted?: boolean
+ transactionStarted?: boolean
+ transactionStart?: Date
+ transactionId?: number
+ transactionSetInterval?: NodeJS.Timeout
+ transactionIdTag?: string
+ energyActiveImportRegisterValue?: number // In Wh
+ transactionEnergyActiveImportRegisterValue?: number // In Wh
+ transactionBeginMeterValue?: MeterValue
+ chargingProfiles?: ChargingProfile[]
+ reservation?: Reservation
}
-export type EmptyObject = Record<string, never>;
+export type EmptyObject = Record<string, never>
-import type { JsonType } from './JsonType.js';
+import type { JsonType } from './JsonType.js'
export interface HandleErrorParams<T extends JsonType> {
- throwError?: boolean;
- consoleOut?: boolean;
- errorResponse?: T;
+ throwError?: boolean
+ consoleOut?: boolean
+ errorResponse?: T
}
-import type { ConnectorStatus } from './ConnectorStatus.js';
-import type { AvailabilityType } from './ocpp/Requests.js';
+import type { ConnectorStatus } from './ConnectorStatus.js'
+import type { AvailabilityType } from './ocpp/Requests.js'
export interface EvseTemplate {
- Connectors: Record<string, ConnectorStatus>;
+ Connectors: Record<string, ConnectorStatus>
}
export interface EvseStatus {
- connectors: Map<number, ConnectorStatus>;
- availability: AvailabilityType;
+ connectors: Map<number, ConnectorStatus>
+ availability: AvailabilityType
}
ChargingStationConfiguration = 'charging station configuration',
ChargingStationTemplate = 'charging station template',
PerformanceRecords = 'performance records',
- JsonSchema = 'json schema',
+ JsonSchema = 'json schema'
}
-type JsonPrimitive = string | number | boolean | Date | null;
+type JsonPrimitive = string | number | boolean | Date | null
export type JsonObject = {
- [key in string]?: JsonType;
-};
+ [key in string]?: JsonType
+}
-export type JsonType = JsonPrimitive | JsonType[] | JsonObject;
+export type JsonType = JsonPrimitive | JsonType[] | JsonObject
-import type { SampledValue } from './ocpp/MeterValues.js';
+import type { SampledValue } from './ocpp/MeterValues.js'
export type SampledValueTemplate = SampledValue & {
- fluctuationPercent?: number;
- minimumValue?: number;
-};
+ fluctuationPercent?: number
+ minimumValue?: number
+}
export interface MeasurandPerPhaseSampledValueTemplates {
- L1?: SampledValueTemplate;
- L2?: SampledValueTemplate;
- L3?: SampledValueTemplate;
+ L1?: SampledValueTemplate
+ L2?: SampledValueTemplate
+ L3?: SampledValueTemplate
}
export interface MeasurandValues {
- L1: number;
- L2: number;
- L3: number;
- allPhases: number;
+ L1: number
+ L2: number
+ L3: number
+ allPhases: number
}
-import type { IncomingRequestCommand, RequestCommand } from './ocpp/Requests.js';
-import type { CircularArray } from '../utils/index.js';
-import type { WorkerData } from '../worker/index.js';
+import type { IncomingRequestCommand, RequestCommand } from './ocpp/Requests.js'
+import type { CircularArray } from '../utils/index.js'
+import type { WorkerData } from '../worker/index.js'
export interface TimestampedData {
- timestamp: number;
- value: number;
+ timestamp: number
+ value: number
}
export type StatisticsData = Partial<{
- requestCount: number;
- responseCount: number;
- errorCount: number;
- timeMeasurementCount: number;
- measurementTimeSeries: CircularArray<TimestampedData>;
- currentTimeMeasurement: number;
- minTimeMeasurement: number;
- maxTimeMeasurement: number;
- totalTimeMeasurement: number;
- avgTimeMeasurement: number;
- medTimeMeasurement: number;
- ninetyFiveThPercentileTimeMeasurement: number;
- stdDevTimeMeasurement: number;
-}>;
+ requestCount: number
+ responseCount: number
+ errorCount: number
+ timeMeasurementCount: number
+ measurementTimeSeries: CircularArray<TimestampedData>
+ currentTimeMeasurement: number
+ minTimeMeasurement: number
+ maxTimeMeasurement: number
+ totalTimeMeasurement: number
+ avgTimeMeasurement: number
+ medTimeMeasurement: number
+ ninetyFiveThPercentileTimeMeasurement: number
+ stdDevTimeMeasurement: number
+}>
export type Statistics = {
- id: string;
- name: string;
- uri: string;
- createdAt: Date;
- updatedAt?: Date;
- statisticsData: Map<string | RequestCommand | IncomingRequestCommand, StatisticsData>;
-} & WorkerData;
+ id: string
+ name: string
+ uri: string
+ createdAt: Date
+ updatedAt?: Date
+ statisticsData: Map<string | RequestCommand | IncomingRequestCommand, StatisticsData>
+} & WorkerData
-import type { Configuration } from '@mikro-orm/core';
+import type { Configuration } from '@mikro-orm/core'
-export type MikroOrmDbType = keyof typeof Configuration.PLATFORMS;
+export type MikroOrmDbType = keyof typeof Configuration.PLATFORMS
export enum StorageType {
JSON_FILE = 'jsonfile',
MONGO_DB = 'mongodb',
MYSQL = 'mysql',
MARIA_DB = 'mariadb',
- SQLITE = 'sqlite',
+ SQLITE = 'sqlite'
}
export enum DBName {
MONGO_DB = 'MongoDB',
MYSQL = 'MySQL',
MARIA_DB = 'MariaDB',
- SQLITE = 'SQLite',
+ SQLITE = 'SQLite'
}
-import type { JsonObject } from './JsonType.js';
-import type { BroadcastChannelResponsePayload } from './WorkerBroadcastChannel.js';
+import type { JsonObject } from './JsonType.js'
+import type { BroadcastChannelResponsePayload } from './WorkerBroadcastChannel.js'
export enum Protocol {
- UI = 'ui',
+ UI = 'ui'
}
export enum ApplicationProtocol {
HTTP = 'http',
- WS = 'ws',
+ WS = 'ws'
}
export enum AuthenticationType {
- BASIC_AUTH = 'basic-auth',
+ BASIC_AUTH = 'basic-auth'
}
export enum ProtocolVersion {
- '0.0.1' = '0.0.1',
+ '0.0.1' = '0.0.1'
}
-export type ProtocolRequest = [string, ProcedureName, RequestPayload];
-export type ProtocolResponse = [string, ResponsePayload];
+export type ProtocolRequest = [string, ProcedureName, RequestPayload]
+export type ProtocolResponse = [string, ResponsePayload]
export type ProtocolRequestHandler = (
uuid?: string,
procedureName?: ProcedureName,
- payload?: RequestPayload,
-) => undefined | Promise<undefined> | ResponsePayload | Promise<ResponsePayload>;
+ payload?: RequestPayload
+) => undefined | Promise<undefined> | ResponsePayload | Promise<ResponsePayload>
export enum ProcedureName {
START_SIMULATOR = 'startSimulator',
METER_VALUES = 'meterValues',
DATA_TRANSFER = 'dataTransfer',
DIAGNOSTICS_STATUS_NOTIFICATION = 'diagnosticsStatusNotification',
- FIRMWARE_STATUS_NOTIFICATION = 'firmwareStatusNotification',
+ FIRMWARE_STATUS_NOTIFICATION = 'firmwareStatusNotification'
}
export interface RequestPayload extends JsonObject {
- hashIds?: string[];
- connectorIds?: number[];
+ hashIds?: string[]
+ connectorIds?: number[]
}
export enum ResponseStatus {
SUCCESS = 'success',
- FAILURE = 'failure',
+ FAILURE = 'failure'
}
export interface ResponsePayload extends JsonObject {
- status: ResponseStatus;
- hashIdsSucceeded?: string[];
- hashIdsFailed?: string[];
- responsesFailed?: BroadcastChannelResponsePayload[];
+ status: ResponseStatus
+ hashIdsSucceeded?: string[]
+ hashIdsFailed?: string[]
+ responsesFailed?: BroadcastChannelResponsePayload[]
}
1012: 'Service Restart',
1013: 'Try Again Later',
1014: 'Bad Gateway',
- 1015: 'TLS Handshake',
- });
+ 1015: 'TLS Handshake'
+ })
export enum WebSocketCloseEventStatusCode {
CLOSE_NORMAL = 1000,
CLOSE_SERVICE_RESTART = 1012,
CLOSE_TRY_AGAIN_LATER = 1013,
CLOSE_BAD_GATEWAY = 1014,
- CLOSE_TLS_HANDSHAKE = 1015,
+ CLOSE_TLS_HANDSHAKE = 1015
}
export interface WSError extends Error {
- code?: string;
+ code?: string
}
-import type { RequestPayload, ResponsePayload } from './UIProtocol.js';
+import type { RequestPayload, ResponsePayload } from './UIProtocol.js'
export type BroadcastChannelRequest = [
string,
BroadcastChannelProcedureName,
- BroadcastChannelRequestPayload,
-];
-export type BroadcastChannelResponse = [string, BroadcastChannelResponsePayload];
+ BroadcastChannelRequestPayload
+]
+export type BroadcastChannelResponse = [string, BroadcastChannelResponsePayload]
export enum BroadcastChannelProcedureName {
START_CHARGING_STATION = 'startChargingStation',
METER_VALUES = 'meterValues',
DATA_TRANSFER = 'dataTransfer',
DIAGNOSTICS_STATUS_NOTIFICATION = 'diagnosticsStatusNotification',
- FIRMWARE_STATUS_NOTIFICATION = 'firmwareStatusNotification',
+ FIRMWARE_STATUS_NOTIFICATION = 'firmwareStatusNotification'
}
export interface BroadcastChannelRequestPayload extends RequestPayload {
- connectorId?: number;
- transactionId?: number;
+ connectorId?: number
+ transactionId?: number
}
export interface BroadcastChannelResponsePayload
extends Omit<ResponsePayload, 'hashIdsSucceeded' | 'hashIdsFailed' | 'responsesFailed'> {
- hashId: string;
+ hashId: string
}
export interface MessageEvent {
- data: BroadcastChannelRequest | BroadcastChannelResponse;
+ data: BroadcastChannelRequest | BroadcastChannelResponse
}
ProtocolVersion,
type RequestPayload,
type ResponsePayload,
- ResponseStatus,
-} from './UIProtocol.js';
+ ResponseStatus
+} from './UIProtocol.js'
export {
type AutomaticTransactionGeneratorConfiguration,
type ChargingStationAutomaticTransactionGeneratorConfiguration,
IdTagDistribution,
- type Status,
-} from './AutomaticTransactionGenerator.js';
-export { type GenericResponse, GenericStatus, RegistrationStatusEnumType } from './ocpp/Common.js';
+ type Status
+} from './AutomaticTransactionGenerator.js'
+export { type GenericResponse, GenericStatus, RegistrationStatusEnumType } from './ocpp/Common.js'
export {
AvailabilityType,
type BootNotificationRequest,
type RequestParams,
type ResponseCallback,
type ResponseType,
- type StatusNotificationRequest,
-} from './ocpp/Requests.js';
+ type StatusNotificationRequest
+} from './ocpp/Requests.js'
export {
AvailabilityStatus,
type BootNotificationResponse,
type ResponseHandler,
type StatusNotificationResponse,
TriggerMessageStatus,
- UnlockStatus,
-} from './ocpp/Responses.js';
+ UnlockStatus
+} from './ocpp/Responses.js'
export {
AuthorizationStatus,
type AuthorizeRequest,
type StartTransactionResponse,
StopTransactionReason,
type StopTransactionRequest,
- type StopTransactionResponse,
-} from './ocpp/Transaction.js';
-export { BootReasonEnumType, OCPP20ConnectorStatusEnumType } from './ocpp/2.0/Common.js';
+ type StopTransactionResponse
+} from './ocpp/Transaction.js'
+export { BootReasonEnumType, OCPP20ConnectorStatusEnumType } from './ocpp/2.0/Common.js'
export {
BroadcastChannelProcedureName,
type BroadcastChannelRequest,
type BroadcastChannelRequestPayload,
type BroadcastChannelResponse,
type BroadcastChannelResponsePayload,
- type MessageEvent,
-} from './WorkerBroadcastChannel.js';
+ type MessageEvent
+} from './WorkerBroadcastChannel.js'
export {
type ChangeConfigurationRequest,
type GetConfigurationRequest,
type RemoteStopTransactionRequest,
type ResetRequest,
type SetChargingProfileRequest,
- type UnlockConnectorRequest,
-} from './ocpp/1.6/Requests.js';
+ type UnlockConnectorRequest
+} from './ocpp/1.6/Requests.js'
export {
type ChangeConfigurationResponse,
type GetConfigurationResponse,
type OCPP16TriggerMessageResponse,
type OCPP16UpdateFirmwareResponse,
type SetChargingProfileResponse,
- type UnlockConnectorResponse,
-} from './ocpp/1.6/Responses.js';
-export { ChargePointErrorCode } from './ocpp/ChargePointErrorCode.js';
+ type UnlockConnectorResponse
+} from './ocpp/1.6/Responses.js'
+export { ChargePointErrorCode } from './ocpp/ChargePointErrorCode.js'
export {
type ChargingProfile,
ChargingProfileKindType,
ChargingRateUnitType,
type ChargingSchedulePeriod,
- RecurrencyKindType,
-} from './ocpp/ChargingProfile.js';
+ RecurrencyKindType
+} from './ocpp/ChargingProfile.js'
export type {
ChargingStationConfiguration,
- EvseStatusConfiguration,
-} from './ChargingStationConfiguration.js';
+ EvseStatusConfiguration
+} from './ChargingStationConfiguration.js'
export {
type ChargingStationData,
type ChargingStationWorkerData,
type ChargingStationWorkerMessage,
type ChargingStationWorkerMessageData,
ChargingStationWorkerMessageEvents,
- type EvseStatusWorkerType,
-} from './ChargingStationWorker.js';
-export type { ChargingStationInfo } from './ChargingStationInfo.js';
+ type EvseStatusWorkerType
+} from './ChargingStationWorker.js'
+export type { ChargingStationInfo } from './ChargingStationInfo.js'
export type {
ChargingStationOcppConfiguration,
- ConfigurationKey,
-} from './ChargingStationOcppConfiguration.js';
+ ConfigurationKey
+} from './ChargingStationOcppConfiguration.js'
export {
AmpereUnits,
type ChargingStationTemplate,
type FirmwareUpgrade,
PowerUnits,
Voltage,
- type WsOptions,
-} from './ChargingStationTemplate.js';
+ type WsOptions
+} from './ChargingStationTemplate.js'
export {
ApplicationProtocolVersion,
type ConfigurationData,
type StorageConfiguration,
SupervisionUrlDistribution,
type UIServerConfiguration,
- type WorkerConfiguration,
-} from './ConfigurationData.js';
+ type WorkerConfiguration
+} from './ConfigurationData.js'
export {
type ConfigurationKeyType,
ConnectorPhaseRotation,
type OCPPConfigurationKey,
StandardParametersKey,
SupportedFeatureProfiles,
- VendorParametersKey,
-} from './ocpp/Configuration.js';
-export type { ConnectorStatus } from './ConnectorStatus.js';
-export { ConnectorStatusEnum, type ConnectorStatusTransition } from './ocpp/ConnectorStatusEnum.js';
-export { DBName, type MikroOrmDbType, StorageType } from './Storage.js';
-export type { EmptyObject } from './EmptyObject.js';
-export { ErrorType } from './ocpp/ErrorType.js';
-export type { EvseTemplate, EvseStatus } from './Evse.js';
-export { FileType } from './FileType.js';
-export type { HandleErrorParams } from './Error.js';
-export type { JsonObject, JsonType } from './JsonType.js';
+ VendorParametersKey
+} from './ocpp/Configuration.js'
+export type { ConnectorStatus } from './ConnectorStatus.js'
+export { ConnectorStatusEnum, type ConnectorStatusTransition } from './ocpp/ConnectorStatusEnum.js'
+export { DBName, type MikroOrmDbType, StorageType } from './Storage.js'
+export type { EmptyObject } from './EmptyObject.js'
+export { ErrorType } from './ocpp/ErrorType.js'
+export type { EvseTemplate, EvseStatus } from './Evse.js'
+export { FileType } from './FileType.js'
+export type { HandleErrorParams } from './Error.js'
+export type { JsonObject, JsonType } from './JsonType.js'
export type {
MeasurandPerPhaseSampledValueTemplates,
- SampledValueTemplate,
-} from './MeasurandPerPhaseSampledValueTemplates.js';
-export type { MeasurandValues } from './MeasurandValues.js';
-export { MessageType } from './ocpp/MessageType.js';
+ SampledValueTemplate
+} from './MeasurandPerPhaseSampledValueTemplates.js'
+export type { MeasurandValues } from './MeasurandValues.js'
+export { MessageType } from './ocpp/MessageType.js'
export {
type MeterValue,
MeterValueContext,
MeterValueMeasurand,
MeterValuePhase,
MeterValueUnit,
- type SampledValue,
-} from './ocpp/MeterValues.js';
+ type SampledValue
+} from './ocpp/MeterValues.js'
export {
type OCPP16MeterValue,
OCPP16MeterValueContext,
OCPP16MeterValueUnit,
type OCPP16MeterValuesRequest,
type OCPP16MeterValuesResponse,
- type OCPP16SampledValue,
-} from './ocpp/1.6/MeterValues.js';
+ type OCPP16SampledValue
+} from './ocpp/1.6/MeterValues.js'
export {
OCPP16AuthorizationStatus,
type OCPP16AuthorizeRequest,
type OCPP16StartTransactionResponse,
OCPP16StopTransactionReason,
type OCPP16StopTransactionRequest,
- type OCPP16StopTransactionResponse,
-} from './ocpp/1.6/Transaction.js';
-export { OCPP16ChargePointErrorCode } from './ocpp/1.6/ChargePointErrorCode.js';
-export { OCPP16ChargePointStatus } from './ocpp/1.6/ChargePointStatus.js';
+ type OCPP16StopTransactionResponse
+} from './ocpp/1.6/Transaction.js'
+export { OCPP16ChargePointErrorCode } from './ocpp/1.6/ChargePointErrorCode.js'
+export { OCPP16ChargePointStatus } from './ocpp/1.6/ChargePointStatus.js'
export {
type OCPP16ChargingProfile,
OCPP16ChargingProfilePurposeType,
OCPP16ChargingRateUnitType,
type OCPP16ChargingSchedule,
- type OCPP16ChargingSchedulePeriod,
-} from './ocpp/1.6/ChargingProfile.js';
+ type OCPP16ChargingSchedulePeriod
+} from './ocpp/1.6/ChargingProfile.js'
export {
OCPP16StandardParametersKey,
- OCPP16SupportedFeatureProfiles,
-} from './ocpp/1.6/Configuration.js';
-export { OCPP16DiagnosticsStatus } from './ocpp/1.6/DiagnosticsStatus.js';
+ OCPP16SupportedFeatureProfiles
+} from './ocpp/1.6/Configuration.js'
+export { OCPP16DiagnosticsStatus } from './ocpp/1.6/DiagnosticsStatus.js'
export {
type OCPP20BootNotificationRequest,
type OCPP20ClearCacheRequest,
type OCPP20HeartbeatRequest,
OCPP20IncomingRequestCommand,
OCPP20RequestCommand,
- type OCPP20StatusNotificationRequest,
-} from './ocpp/2.0/Requests.js';
+ type OCPP20StatusNotificationRequest
+} from './ocpp/2.0/Requests.js'
export type {
OCPP20BootNotificationResponse,
OCPP20ClearCacheResponse,
OCPP20HeartbeatResponse,
- OCPP20StatusNotificationResponse,
-} from './ocpp/2.0/Responses.js';
-export { OCPP20OptionalVariableName } from './ocpp/2.0/Variables.js';
-export { OCPPVersion } from './ocpp/OCPPVersion.js';
-export { PerformanceData } from './orm/entities/PerformanceData.js';
-export { PerformanceRecord } from './orm/entities/PerformanceRecord.js';
-export type { Statistics, TimestampedData } from './Statistics.js';
+ OCPP20StatusNotificationResponse
+} from './ocpp/2.0/Responses.js'
+export { OCPP20OptionalVariableName } from './ocpp/2.0/Variables.js'
+export { OCPPVersion } from './ocpp/OCPPVersion.js'
+export { PerformanceData } from './orm/entities/PerformanceData.js'
+export { PerformanceRecord } from './orm/entities/PerformanceRecord.js'
+export type { Statistics, TimestampedData } from './Statistics.js'
export {
type WSError,
WebSocketCloseEventStatusCode,
- WebSocketCloseEventStatusString,
-} from './WebSocket.js';
+ WebSocketCloseEventStatusString
+} from './WebSocket.js'
export {
type Reservation,
type ReservationKey,
- ReservationTerminationReason,
-} from './ocpp/Reservation.js';
-export { ChargingStationEvents } from './ChargingStationEvents.js';
+ ReservationTerminationReason
+} from './ocpp/Reservation.js'
+export { ChargingStationEvents } from './ChargingStationEvents.js'
READER_FAILURE = 'ReaderFailure',
RESET_FAILURE = 'ResetFailure',
UNDER_VOLTAGE = 'UnderVoltage',
- WEAK_SIGNAL = 'WeakSignal',
+ WEAK_SIGNAL = 'WeakSignal'
}
Finishing = 'Finishing',
Reserved = 'Reserved',
Unavailable = 'Unavailable',
- Faulted = 'Faulted',
+ Faulted = 'Faulted'
}
-import type { JsonObject } from '../../JsonType.js';
+import type { JsonObject } from '../../JsonType.js'
export interface OCPP16ChargingProfile extends JsonObject {
- chargingProfileId: number;
- transactionId?: number;
- stackLevel: number;
- chargingProfilePurpose: OCPP16ChargingProfilePurposeType;
- chargingProfileKind: OCPP16ChargingProfileKindType;
- recurrencyKind?: OCPP16RecurrencyKindType;
- validFrom?: Date;
- validTo?: Date;
- chargingSchedule: OCPP16ChargingSchedule;
+ chargingProfileId: number
+ transactionId?: number
+ stackLevel: number
+ chargingProfilePurpose: OCPP16ChargingProfilePurposeType
+ chargingProfileKind: OCPP16ChargingProfileKindType
+ recurrencyKind?: OCPP16RecurrencyKindType
+ validFrom?: Date
+ validTo?: Date
+ chargingSchedule: OCPP16ChargingSchedule
}
export interface OCPP16ChargingSchedule extends JsonObject {
- startSchedule?: Date;
- duration?: number;
- chargingRateUnit: OCPP16ChargingRateUnitType;
- chargingSchedulePeriod: OCPP16ChargingSchedulePeriod[];
- minChargeRate?: number;
+ startSchedule?: Date
+ duration?: number
+ chargingRateUnit: OCPP16ChargingRateUnitType
+ chargingSchedulePeriod: OCPP16ChargingSchedulePeriod[]
+ minChargeRate?: number
}
export interface OCPP16ChargingSchedulePeriod extends JsonObject {
- startPeriod: number;
- limit: number;
- numberPhases?: number;
+ startPeriod: number
+ limit: number
+ numberPhases?: number
}
export enum OCPP16ChargingRateUnitType {
WATT = 'W',
- AMPERE = 'A',
+ AMPERE = 'A'
}
export enum OCPP16ChargingProfileKindType {
ABSOLUTE = 'Absolute',
RECURRING = 'Recurring',
- RELATIVE = 'Relative',
+ RELATIVE = 'Relative'
}
export enum OCPP16ChargingProfilePurposeType {
CHARGE_POINT_MAX_PROFILE = 'ChargePointMaxProfile',
TX_DEFAULT_PROFILE = 'TxDefaultProfile',
- TX_PROFILE = 'TxProfile',
+ TX_PROFILE = 'TxProfile'
}
export enum OCPP16RecurrencyKindType {
DAILY = 'Daily',
- WEEKLY = 'Weekly',
+ WEEKLY = 'Weekly'
}
LocalAuthListManagement = 'LocalAuthListManagement',
Reservation = 'Reservation',
SmartCharging = 'SmartCharging',
- RemoteTrigger = 'RemoteTrigger',
+ RemoteTrigger = 'RemoteTrigger'
}
export enum OCPP16StandardParametersKey {
ChargingScheduleAllowedChargingRateUnit = 'ChargingScheduleAllowedChargingRateUnit',
ChargingScheduleMaxPeriods = 'ChargingScheduleMaxPeriods',
ConnectorSwitch3to1PhaseSupported = 'ConnectorSwitch3to1PhaseSupported',
- MaxChargingProfilesInstalled = 'MaxChargingProfilesInstalled',
+ MaxChargingProfilesInstalled = 'MaxChargingProfilesInstalled'
}
export enum OCPP16VendorParametersKey {
- ConnectionUrl = 'ConnectionUrl',
+ ConnectionUrl = 'ConnectionUrl'
}
Idle = 'Idle',
Uploaded = 'Uploaded',
UploadFailed = 'UploadFailed',
- Uploading = 'Uploading',
+ Uploading = 'Uploading'
}
-import type { EmptyObject } from '../../EmptyObject.js';
-import type { JsonObject } from '../../JsonType.js';
+import type { EmptyObject } from '../../EmptyObject.js'
+import type { JsonObject } from '../../JsonType.js'
export enum OCPP16MeterValueUnit {
WATT_HOUR = 'Wh',
TEMP_CELSIUS = 'Celsius',
TEMP_FAHRENHEIT = 'Fahrenheit',
TEMP_KELVIN = 'K',
- PERCENT = 'Percent',
+ PERCENT = 'Percent'
}
export enum OCPP16MeterValueContext {
SAMPLE_PERIODIC = 'Sample.Periodic',
TRANSACTION_BEGIN = 'Transaction.Begin',
TRANSACTION_END = 'Transaction.End',
- TRIGGER = 'Trigger',
+ TRIGGER = 'Trigger'
}
export enum OCPP16MeterValueMeasurand {
FAN_RPM = 'RPM',
STATE_OF_CHARGE = 'SoC',
TEMPERATURE = 'Temperature',
- VOLTAGE = 'Voltage',
+ VOLTAGE = 'Voltage'
}
export enum OCPP16MeterValueLocation {
CABLE = 'Cable',
EV = 'EV',
INLET = 'Inlet',
- OUTLET = 'Outlet',
+ OUTLET = 'Outlet'
}
export enum OCPP16MeterValuePhase {
L3_N = 'L3-N',
L1_L2 = 'L1-L2',
L2_L3 = 'L2-L3',
- L3_L1 = 'L3-L1',
+ L3_L1 = 'L3-L1'
}
enum OCPP16MeterValueFormat {
RAW = 'Raw',
- SIGNED_DATA = 'SignedData',
+ SIGNED_DATA = 'SignedData'
}
export interface OCPP16SampledValue extends JsonObject {
- value: string;
- unit?: OCPP16MeterValueUnit;
- context?: OCPP16MeterValueContext;
- measurand?: OCPP16MeterValueMeasurand;
- phase?: OCPP16MeterValuePhase;
- location?: OCPP16MeterValueLocation;
- format?: OCPP16MeterValueFormat;
+ value: string
+ unit?: OCPP16MeterValueUnit
+ context?: OCPP16MeterValueContext
+ measurand?: OCPP16MeterValueMeasurand
+ phase?: OCPP16MeterValuePhase
+ location?: OCPP16MeterValueLocation
+ format?: OCPP16MeterValueFormat
}
export interface OCPP16MeterValue extends JsonObject {
- timestamp: Date;
- sampledValue: OCPP16SampledValue[];
+ timestamp: Date
+ sampledValue: OCPP16SampledValue[]
}
export interface OCPP16MeterValuesRequest extends JsonObject {
- connectorId: number;
- transactionId?: number;
- meterValue: OCPP16MeterValue[];
+ connectorId: number
+ transactionId?: number
+ meterValue: OCPP16MeterValue[]
}
-export type OCPP16MeterValuesResponse = EmptyObject;
+export type OCPP16MeterValuesResponse = EmptyObject
-import type { OCPP16ChargePointErrorCode } from './ChargePointErrorCode.js';
-import type { OCPP16ChargePointStatus } from './ChargePointStatus.js';
+import type { OCPP16ChargePointErrorCode } from './ChargePointErrorCode.js'
+import type { OCPP16ChargePointStatus } from './ChargePointStatus.js'
import type {
OCPP16ChargingProfile,
OCPP16ChargingProfilePurposeType,
- OCPP16ChargingRateUnitType,
-} from './ChargingProfile.js';
-import type { OCPP16StandardParametersKey, OCPP16VendorParametersKey } from './Configuration.js';
-import type { OCPP16DiagnosticsStatus } from './DiagnosticsStatus.js';
-import type { EmptyObject } from '../../EmptyObject.js';
-import type { JsonObject } from '../../JsonType.js';
+ OCPP16ChargingRateUnitType
+} from './ChargingProfile.js'
+import type { OCPP16StandardParametersKey, OCPP16VendorParametersKey } from './Configuration.js'
+import type { OCPP16DiagnosticsStatus } from './DiagnosticsStatus.js'
+import type { EmptyObject } from '../../EmptyObject.js'
+import type { JsonObject } from '../../JsonType.js'
export enum OCPP16RequestCommand {
BOOT_NOTIFICATION = 'BootNotification',
METER_VALUES = 'MeterValues',
DIAGNOSTICS_STATUS_NOTIFICATION = 'DiagnosticsStatusNotification',
FIRMWARE_STATUS_NOTIFICATION = 'FirmwareStatusNotification',
- DATA_TRANSFER = 'DataTransfer',
+ DATA_TRANSFER = 'DataTransfer'
}
export enum OCPP16IncomingRequestCommand {
DATA_TRANSFER = 'DataTransfer',
UPDATE_FIRMWARE = 'UpdateFirmware',
RESERVE_NOW = 'ReserveNow',
- CANCEL_RESERVATION = 'CancelReservation',
+ CANCEL_RESERVATION = 'CancelReservation'
}
-export type OCPP16HeartbeatRequest = EmptyObject;
+export type OCPP16HeartbeatRequest = EmptyObject
export interface OCPP16BootNotificationRequest extends JsonObject {
- chargePointVendor: string;
- chargePointModel: string;
- chargePointSerialNumber?: string;
- chargeBoxSerialNumber?: string;
- firmwareVersion?: string;
- iccid?: string;
- imsi?: string;
- meterType?: string;
- meterSerialNumber?: string;
+ chargePointVendor: string
+ chargePointModel: string
+ chargePointSerialNumber?: string
+ chargeBoxSerialNumber?: string
+ firmwareVersion?: string
+ iccid?: string
+ imsi?: string
+ meterType?: string
+ meterSerialNumber?: string
}
export interface OCPP16StatusNotificationRequest extends JsonObject {
- connectorId: number;
- errorCode: OCPP16ChargePointErrorCode;
- status: OCPP16ChargePointStatus;
- info?: string;
- timestamp?: Date;
- vendorId?: string;
- vendorErrorCode?: string;
+ connectorId: number
+ errorCode: OCPP16ChargePointErrorCode
+ status: OCPP16ChargePointStatus
+ info?: string
+ timestamp?: Date
+ vendorId?: string
+ vendorErrorCode?: string
}
-export type OCPP16ClearCacheRequest = EmptyObject;
+export type OCPP16ClearCacheRequest = EmptyObject
-type OCPP16ConfigurationKey = string | OCPP16StandardParametersKey | OCPP16VendorParametersKey;
+type OCPP16ConfigurationKey = string | OCPP16StandardParametersKey | OCPP16VendorParametersKey
export interface ChangeConfigurationRequest extends JsonObject {
- key: OCPP16ConfigurationKey;
- value: string;
+ key: OCPP16ConfigurationKey
+ value: string
}
export interface RemoteStartTransactionRequest extends JsonObject {
- connectorId: number;
- idTag: string;
- chargingProfile?: OCPP16ChargingProfile;
+ connectorId: number
+ idTag: string
+ chargingProfile?: OCPP16ChargingProfile
}
export interface RemoteStopTransactionRequest extends JsonObject {
- transactionId: number;
+ transactionId: number
}
export interface UnlockConnectorRequest extends JsonObject {
- connectorId: number;
+ connectorId: number
}
export interface GetConfigurationRequest extends JsonObject {
- key?: OCPP16ConfigurationKey[];
+ key?: OCPP16ConfigurationKey[]
}
enum ResetType {
HARD = 'Hard',
- SOFT = 'Soft',
+ SOFT = 'Soft'
}
export interface ResetRequest extends JsonObject {
- type: ResetType;
+ type: ResetType
}
export interface OCPP16GetCompositeScheduleRequest extends JsonObject {
- connectorId: number;
- duration: number;
- chargingRateUnit?: OCPP16ChargingRateUnitType;
+ connectorId: number
+ duration: number
+ chargingRateUnit?: OCPP16ChargingRateUnitType
}
export interface SetChargingProfileRequest extends JsonObject {
- connectorId: number;
- csChargingProfiles: OCPP16ChargingProfile;
+ connectorId: number
+ csChargingProfiles: OCPP16ChargingProfile
}
export enum OCPP16AvailabilityType {
Inoperative = 'Inoperative',
- Operative = 'Operative',
+ Operative = 'Operative'
}
export interface OCPP16ChangeAvailabilityRequest extends JsonObject {
- connectorId: number;
- type: OCPP16AvailabilityType;
+ connectorId: number
+ type: OCPP16AvailabilityType
}
export interface OCPP16ClearChargingProfileRequest extends JsonObject {
- id?: number;
- connectorId?: number;
- chargingProfilePurpose?: OCPP16ChargingProfilePurposeType;
- stackLevel?: number;
+ id?: number
+ connectorId?: number
+ chargingProfilePurpose?: OCPP16ChargingProfilePurposeType
+ stackLevel?: number
}
export interface OCPP16UpdateFirmwareRequest extends JsonObject {
- location: string;
- retrieveDate: Date;
- retries?: number;
- retryInterval?: number;
+ location: string
+ retrieveDate: Date
+ retries?: number
+ retryInterval?: number
}
export enum OCPP16FirmwareStatus {
Idle = 'Idle',
InstallationFailed = 'InstallationFailed',
Installing = 'Installing',
- Installed = 'Installed',
+ Installed = 'Installed'
}
export type OCPP16FirmwareStatusNotificationRequest = {
- status: OCPP16FirmwareStatus;
-} & JsonObject;
+ status: OCPP16FirmwareStatus
+} & JsonObject
export interface GetDiagnosticsRequest extends JsonObject {
- location: string;
- retries?: number;
- retryInterval?: number;
- startTime?: Date;
- stopTime?: Date;
+ location: string
+ retries?: number
+ retryInterval?: number
+ startTime?: Date
+ stopTime?: Date
}
export interface OCPP16DiagnosticsStatusNotificationRequest extends JsonObject {
- status: OCPP16DiagnosticsStatus;
+ status: OCPP16DiagnosticsStatus
}
export enum OCPP16MessageTrigger {
FirmwareStatusNotification = 'FirmwareStatusNotification',
Heartbeat = 'Heartbeat',
MeterValues = 'MeterValues',
- StatusNotification = 'StatusNotification',
+ StatusNotification = 'StatusNotification'
}
export interface OCPP16TriggerMessageRequest extends JsonObject {
- requestedMessage: OCPP16MessageTrigger;
- connectorId?: number;
+ requestedMessage: OCPP16MessageTrigger
+ connectorId?: number
}
export enum OCPP16DataTransferVendorId {}
export interface OCPP16DataTransferRequest extends JsonObject {
- vendorId: string;
- messageId?: string;
- data?: string;
+ vendorId: string
+ messageId?: string
+ data?: string
}
export interface OCPP16ReserveNowRequest extends JsonObject {
- connectorId: number;
- expiryDate: Date;
- idTag: string;
- parentIdTag?: string;
- reservationId: number;
+ connectorId: number
+ expiryDate: Date
+ idTag: string
+ parentIdTag?: string
+ reservationId: number
}
export interface OCPP16CancelReservationRequest extends JsonObject {
- reservationId: number;
+ reservationId: number
}
-import type { OCPP16ChargingSchedule } from './ChargingProfile.js';
-import type { EmptyObject } from '../../EmptyObject.js';
-import type { JsonObject } from '../../JsonType.js';
-import type { GenericStatus, RegistrationStatusEnumType } from '../Common.js';
-import type { OCPPConfigurationKey } from '../Configuration.js';
+import type { OCPP16ChargingSchedule } from './ChargingProfile.js'
+import type { EmptyObject } from '../../EmptyObject.js'
+import type { JsonObject } from '../../JsonType.js'
+import type { GenericStatus, RegistrationStatusEnumType } from '../Common.js'
+import type { OCPPConfigurationKey } from '../Configuration.js'
export interface OCPP16HeartbeatResponse extends JsonObject {
- currentTime: Date;
+ currentTime: Date
}
export enum OCPP16UnlockStatus {
UNLOCKED = 'Unlocked',
UNLOCK_FAILED = 'UnlockFailed',
- NOT_SUPPORTED = 'NotSupported',
+ NOT_SUPPORTED = 'NotSupported'
}
export interface UnlockConnectorResponse extends JsonObject {
- status: OCPP16UnlockStatus;
+ status: OCPP16UnlockStatus
}
export enum OCPP16ConfigurationStatus {
ACCEPTED = 'Accepted',
REJECTED = 'Rejected',
REBOOT_REQUIRED = 'RebootRequired',
- NOT_SUPPORTED = 'NotSupported',
+ NOT_SUPPORTED = 'NotSupported'
}
export interface ChangeConfigurationResponse extends JsonObject {
- status: OCPP16ConfigurationStatus;
+ status: OCPP16ConfigurationStatus
}
export interface OCPP16BootNotificationResponse extends JsonObject {
- status: RegistrationStatusEnumType;
- currentTime: Date;
- interval: number;
+ status: RegistrationStatusEnumType
+ currentTime: Date
+ interval: number
}
-export type OCPP16StatusNotificationResponse = EmptyObject;
+export type OCPP16StatusNotificationResponse = EmptyObject
export interface GetConfigurationResponse extends JsonObject {
- configurationKey: OCPPConfigurationKey[];
- unknownKey: string[];
+ configurationKey: OCPPConfigurationKey[]
+ unknownKey: string[]
}
export enum OCPP16ChargingProfileStatus {
ACCEPTED = 'Accepted',
REJECTED = 'Rejected',
- NOT_SUPPORTED = 'NotSupported',
+ NOT_SUPPORTED = 'NotSupported'
}
export interface OCPP16GetCompositeScheduleResponse extends JsonObject {
- status: GenericStatus;
- connectorId?: number;
- scheduleStart?: Date;
- chargingSchedule?: OCPP16ChargingSchedule;
+ status: GenericStatus
+ connectorId?: number
+ scheduleStart?: Date
+ chargingSchedule?: OCPP16ChargingSchedule
}
export interface SetChargingProfileResponse extends JsonObject {
- status: OCPP16ChargingProfileStatus;
+ status: OCPP16ChargingProfileStatus
}
export enum OCPP16AvailabilityStatus {
ACCEPTED = 'Accepted',
REJECTED = 'Rejected',
- SCHEDULED = 'Scheduled',
+ SCHEDULED = 'Scheduled'
}
export interface OCPP16ChangeAvailabilityResponse extends JsonObject {
- status: OCPP16AvailabilityStatus;
+ status: OCPP16AvailabilityStatus
}
export enum OCPP16ClearChargingProfileStatus {
ACCEPTED = 'Accepted',
- UNKNOWN = 'Unknown',
+ UNKNOWN = 'Unknown'
}
export interface OCPP16ClearChargingProfileResponse extends JsonObject {
- status: OCPP16ClearChargingProfileStatus;
+ status: OCPP16ClearChargingProfileStatus
}
-export type OCPP16UpdateFirmwareResponse = EmptyObject;
+export type OCPP16UpdateFirmwareResponse = EmptyObject
-export type OCPP16FirmwareStatusNotificationResponse = EmptyObject;
+export type OCPP16FirmwareStatusNotificationResponse = EmptyObject
export interface GetDiagnosticsResponse extends JsonObject {
- fileName?: string;
+ fileName?: string
}
-export type OCPP16DiagnosticsStatusNotificationResponse = EmptyObject;
+export type OCPP16DiagnosticsStatusNotificationResponse = EmptyObject
export enum OCPP16TriggerMessageStatus {
ACCEPTED = 'Accepted',
REJECTED = 'Rejected',
- NOT_IMPLEMENTED = 'NotImplemented',
+ NOT_IMPLEMENTED = 'NotImplemented'
}
export interface OCPP16TriggerMessageResponse extends JsonObject {
- status: OCPP16TriggerMessageStatus;
+ status: OCPP16TriggerMessageStatus
}
export enum OCPP16DataTransferStatus {
ACCEPTED = 'Accepted',
REJECTED = 'Rejected',
UNKNOWN_MESSAGE_ID = 'UnknownMessageId',
- UNKNOWN_VENDOR_ID = 'UnknownVendorId',
+ UNKNOWN_VENDOR_ID = 'UnknownVendorId'
}
export interface OCPP16DataTransferResponse extends JsonObject {
- status: OCPP16DataTransferStatus;
- data?: string;
+ status: OCPP16DataTransferStatus
+ data?: string
}
export enum OCPP16ReservationStatus {
OCCUPIED = 'Occupied',
REJECTED = 'Rejected',
UNAVAILABLE = 'Unavailable',
- NOT_SUPPORTED = 'NotSupported',
+ NOT_SUPPORTED = 'NotSupported'
}
export interface OCPP16ReserveNowResponse extends JsonObject {
- status: OCPP16ReservationStatus;
+ status: OCPP16ReservationStatus
}
-import type { OCPP16MeterValue } from './MeterValues.js';
-import type { JsonObject } from '../../JsonType.js';
+import type { OCPP16MeterValue } from './MeterValues.js'
+import type { JsonObject } from '../../JsonType.js'
export enum OCPP16StopTransactionReason {
EMERGENCY_STOP = 'EmergencyStop',
REMOTE = 'Remote',
SOFT_RESET = 'SoftReset',
UNLOCK_COMMAND = 'UnlockCommand',
- DE_AUTHORIZED = 'DeAuthorized',
+ DE_AUTHORIZED = 'DeAuthorized'
}
export enum OCPP16AuthorizationStatus {
BLOCKED = 'Blocked',
EXPIRED = 'Expired',
INVALID = 'Invalid',
- CONCURRENT_TX = 'ConcurrentTx',
+ CONCURRENT_TX = 'ConcurrentTx'
}
interface IdTagInfo extends JsonObject {
- status: OCPP16AuthorizationStatus;
- parentIdTag?: string;
- expiryDate?: Date;
+ status: OCPP16AuthorizationStatus
+ parentIdTag?: string
+ expiryDate?: Date
}
export interface OCPP16AuthorizeRequest extends JsonObject {
- idTag: string;
+ idTag: string
}
export interface OCPP16AuthorizeResponse extends JsonObject {
- idTagInfo: IdTagInfo;
+ idTagInfo: IdTagInfo
}
export interface OCPP16StartTransactionRequest extends JsonObject {
- connectorId: number;
- idTag: string;
- meterStart: number;
- timestamp: Date;
- reservationId?: number;
+ connectorId: number
+ idTag: string
+ meterStart: number
+ timestamp: Date
+ reservationId?: number
}
export interface OCPP16StartTransactionResponse extends JsonObject {
- idTagInfo: IdTagInfo;
- transactionId: number;
+ idTagInfo: IdTagInfo
+ transactionId: number
}
export interface OCPP16StopTransactionRequest extends JsonObject {
- idTag?: string;
- meterStop: number;
- timestamp: Date;
- transactionId: number;
- reason?: OCPP16StopTransactionReason;
- transactionData?: OCPP16MeterValue[];
+ idTag?: string
+ meterStop: number
+ timestamp: Date
+ transactionId: number
+ reason?: OCPP16StopTransactionReason
+ transactionData?: OCPP16MeterValue[]
}
export interface OCPP16StopTransactionResponse extends JsonObject {
- idTagInfo?: IdTagInfo;
+ idTagInfo?: IdTagInfo
}
-import type { JsonObject } from '../../JsonType.js';
-import type { GenericStatus } from '../Common.js';
+import type { JsonObject } from '../../JsonType.js'
+import type { GenericStatus } from '../Common.js'
export enum DataEnumType {
- // eslint-disable-next-line id-blacklist
string = 'string',
decimal = 'decimal',
integer = 'integer',
dateTime = 'dateTime',
- // eslint-disable-next-line id-blacklist
boolean = 'boolean',
OptionList = 'OptionList',
SequenceList = 'SequenceList',
- MemberList = 'MemberList',
+ MemberList = 'MemberList'
}
export enum BootReasonEnumType {
ScheduledReset = 'ScheduledReset',
Triggered = 'Triggered',
Unknown = 'Unknown',
- Watchdog = 'Watchdog',
+ Watchdog = 'Watchdog'
}
export enum OperationalStatusEnumType {
Operative = 'Operative',
- Inoperative = 'Inoperative',
+ Inoperative = 'Inoperative'
}
export enum OCPP20ConnectorStatusEnumType {
Occupied = 'Occupied',
Reserved = 'Reserved',
Unavailable = 'Unavailable',
- Faulted = 'Faulted',
+ Faulted = 'Faulted'
}
-export type GenericStatusEnumType = GenericStatus;
+export type GenericStatusEnumType = GenericStatus
export enum HashAlgorithmEnumType {
SHA256 = 'SHA256',
SHA384 = 'SHA384',
- SHA512 = 'SHA512',
+ SHA512 = 'SHA512'
}
export enum GetCertificateIdUseEnumType {
MORootCertificate = 'MORootCertificate',
CSMSRootCertificate = 'CSMSRootCertificate',
V2GCertificateChain = 'V2GCertificateChain',
- ManufacturerRootCertificate = 'ManufacturerRootCertificate',
+ ManufacturerRootCertificate = 'ManufacturerRootCertificate'
}
export enum GetCertificateStatusEnumType {
Accepted = 'Accepted',
- Failed = 'Failed',
+ Failed = 'Failed'
}
export enum GetInstalledCertificateStatusEnumType {
Accepted = 'Accepted',
- NotFound = 'NotFound',
+ NotFound = 'NotFound'
}
export enum InstallCertificateStatusEnumType {
Accepted = 'Accepted',
Rejected = 'Rejected',
- Failed = 'Failed',
+ Failed = 'Failed'
}
export enum InstallCertificateUseEnumType {
V2GRootCertificate = 'V2GRootCertificate',
MORootCertificate = 'MORootCertificate',
CSMSRootCertificate = 'CSMSRootCertificate',
- ManufacturerRootCertificate = 'ManufacturerRootCertificate',
+ ManufacturerRootCertificate = 'ManufacturerRootCertificate'
}
export enum DeleteCertificateStatusEnumType {
Accepted = 'Accepted',
Failed = 'Failed',
- NotFound = 'NotFound',
+ NotFound = 'NotFound'
}
export enum CertificateActionEnumType {
Install = 'Install',
- Update = 'Update',
+ Update = 'Update'
}
export enum CertificateSigningUseEnumType {
ChargingStationCertificate = 'ChargingStationCertificate',
- V2GCertificate = 'V2GCertificate',
+ V2GCertificate = 'V2GCertificate'
}
-export type CertificateSignedStatusEnumType = GenericStatusEnumType;
+export type CertificateSignedStatusEnumType = GenericStatusEnumType
export type CertificateHashDataType = {
- hashAlgorithm: HashAlgorithmEnumType;
- issuerNameHash: string;
- issuerKeyHash: string;
- serialNumber: string;
-} & JsonObject;
+ hashAlgorithm: HashAlgorithmEnumType
+ issuerNameHash: string
+ issuerKeyHash: string
+ serialNumber: string
+} & JsonObject
export type CertificateHashDataChainType = {
- certificateType: GetCertificateIdUseEnumType;
- certificateHashData: CertificateHashDataType;
- childCertificateHashData?: CertificateHashDataType;
-} & JsonObject;
+ certificateType: GetCertificateIdUseEnumType
+ certificateHashData: CertificateHashDataType
+ childCertificateHashData?: CertificateHashDataType
+} & JsonObject
export type OCSPRequestDataType = {
- hashAlgorithm: HashAlgorithmEnumType;
- issuerNameHash: string;
- issuerKeyHash: string;
- serialNumber: string;
- responderURL: string;
-} & JsonObject;
+ hashAlgorithm: HashAlgorithmEnumType
+ issuerNameHash: string
+ issuerKeyHash: string
+ serialNumber: string
+ responderURL: string
+} & JsonObject
export type StatusInfoType = {
- reasonCode: string;
- additionalInfo?: string;
-} & JsonObject;
+ reasonCode: string
+ additionalInfo?: string
+} & JsonObject
export type EVSEType = {
- id: number;
- connectorId?: string;
-} & JsonObject;
+ id: number
+ connectorId?: string
+} & JsonObject
import type {
BootReasonEnumType,
InstallCertificateUseEnumType,
- OCPP20ConnectorStatusEnumType,
-} from './Common.js';
-import type { OCPP20SetVariableDataType } from './Variables.js';
-import type { EmptyObject } from '../../EmptyObject.js';
-import type { JsonObject } from '../../JsonType.js';
+ OCPP20ConnectorStatusEnumType
+} from './Common.js'
+import type { OCPP20SetVariableDataType } from './Variables.js'
+import type { EmptyObject } from '../../EmptyObject.js'
+import type { JsonObject } from '../../JsonType.js'
export enum OCPP20RequestCommand {
BOOT_NOTIFICATION = 'BootNotification',
HEARTBEAT = 'Heartbeat',
- STATUS_NOTIFICATION = 'StatusNotification',
+ STATUS_NOTIFICATION = 'StatusNotification'
}
export enum OCPP20IncomingRequestCommand {
CLEAR_CACHE = 'ClearCache',
REQUEST_START_TRANSACTION = 'RequestStartTransaction',
- REQUEST_STOP_TRANSACTION = 'RequestStopTransaction',
+ REQUEST_STOP_TRANSACTION = 'RequestStopTransaction'
}
type ModemType = {
- iccid?: string;
- imsi?: string;
-} & JsonObject;
+ iccid?: string
+ imsi?: string
+} & JsonObject
type ChargingStationType = {
- serialNumber?: string;
- model: string;
- vendorName: string;
- firmwareVersion?: string;
- modem?: ModemType;
-} & JsonObject;
+ serialNumber?: string
+ model: string
+ vendorName: string
+ firmwareVersion?: string
+ modem?: ModemType
+} & JsonObject
export type OCPP20BootNotificationRequest = {
- reason: BootReasonEnumType;
- chargingStation: ChargingStationType;
-} & JsonObject;
+ reason: BootReasonEnumType
+ chargingStation: ChargingStationType
+} & JsonObject
-export type OCPP20HeartbeatRequest = EmptyObject;
+export type OCPP20HeartbeatRequest = EmptyObject
-export type OCPP20ClearCacheRequest = EmptyObject;
+export type OCPP20ClearCacheRequest = EmptyObject
export type OCPP20StatusNotificationRequest = {
- timestamp: Date;
- connectorStatus: OCPP20ConnectorStatusEnumType;
- evseId: number;
- connectorId: number;
-} & JsonObject;
+ timestamp: Date
+ connectorStatus: OCPP20ConnectorStatusEnumType
+ evseId: number
+ connectorId: number
+} & JsonObject
export type OCPP20SetVariablesRequest = {
- setVariableData: OCPP20SetVariableDataType[];
-} & JsonObject;
+ setVariableData: OCPP20SetVariableDataType[]
+} & JsonObject
export type OCPP20InstallCertificateRequest = {
- certificateType: InstallCertificateUseEnumType;
- certificate: string;
-} & JsonObject;
+ certificateType: InstallCertificateUseEnumType
+ certificate: string
+} & JsonObject
import type {
GenericStatusEnumType,
InstallCertificateStatusEnumType,
- StatusInfoType,
-} from './Common.js';
-import type { OCPP20SetVariableResultType } from './Variables.js';
-import type { EmptyObject } from '../../EmptyObject.js';
-import type { JsonObject } from '../../JsonType.js';
-import type { RegistrationStatusEnumType } from '../Common.js';
+ StatusInfoType
+} from './Common.js'
+import type { OCPP20SetVariableResultType } from './Variables.js'
+import type { EmptyObject } from '../../EmptyObject.js'
+import type { JsonObject } from '../../JsonType.js'
+import type { RegistrationStatusEnumType } from '../Common.js'
export type OCPP20BootNotificationResponse = {
- currentTime: Date;
- status: RegistrationStatusEnumType;
- interval: number;
- statusInfo?: StatusInfoType;
-} & JsonObject;
+ currentTime: Date
+ status: RegistrationStatusEnumType
+ interval: number
+ statusInfo?: StatusInfoType
+} & JsonObject
export type OCPP20HeartbeatResponse = {
- currentTime: Date;
-} & JsonObject;
+ currentTime: Date
+} & JsonObject
export type OCPP20ClearCacheResponse = {
- status: GenericStatusEnumType;
- statusInfo?: StatusInfoType;
-} & JsonObject;
+ status: GenericStatusEnumType
+ statusInfo?: StatusInfoType
+} & JsonObject
-export type OCPP20StatusNotificationResponse = EmptyObject;
+export type OCPP20StatusNotificationResponse = EmptyObject
export type OCPP20SetVariablesResponse = {
- setVariableResult: OCPP20SetVariableResultType[];
-} & JsonObject;
+ setVariableResult: OCPP20SetVariableResultType[]
+} & JsonObject
export type OCPP20InstallCertificateResponse = {
- status: InstallCertificateStatusEnumType;
- statusInfo?: StatusInfoType;
-} & JsonObject;
+ status: InstallCertificateStatusEnumType
+ statusInfo?: StatusInfoType
+} & JsonObject
-import type { EVSEType, StatusInfoType } from './Common.js';
-import type { JsonObject } from '../../JsonType.js';
+import type { EVSEType, StatusInfoType } from './Common.js'
+import type { JsonObject } from '../../JsonType.js'
enum OCPP20ComponentName {
AlignedDataCtrlr = 'AlignedDataCtrlr',
SecurityCtrlr = 'SecurityCtrlr',
SmartChargingCtrlr = 'SmartChargingCtrlr',
TariffCostCtrlr = 'TariffCostCtrlr',
- TxCtrlr = 'TxCtrlr',
+ TxCtrlr = 'TxCtrlr'
}
export enum OCPP20RequiredVariableName {
TxEndedMeasurands = 'TxEndedMeasurands',
TxStartedMeasurands = 'TxStartedMeasurands',
TxUpdatedMeasurands = 'TxUpdatedMeasurands',
- TxUpdatedInterval = 'TxUpdatedInterval',
+ TxUpdatedInterval = 'TxUpdatedInterval'
}
export enum OCPP20OptionalVariableName {
HeartbeatInterval = 'HeartbeatInterval',
- WebSocketPingInterval = 'WebSocketPingInterval',
+ WebSocketPingInterval = 'WebSocketPingInterval'
}
export enum OCPP20VendorVariableName {
- ConnectionUrl = 'ConnectionUrl',
+ ConnectionUrl = 'ConnectionUrl'
}
enum AttributeEnumType {
Actual = 'Actual',
Target = 'Target',
MinSet = 'MinSet',
- MaxSet = 'MaxSet',
+ MaxSet = 'MaxSet'
}
type ComponentType = {
- name: string | OCPP20ComponentName;
- instance?: string;
- evse?: EVSEType;
-} & JsonObject;
+ name: string | OCPP20ComponentName
+ instance?: string
+ evse?: EVSEType
+} & JsonObject
type VariableName =
| string
| OCPP20RequiredVariableName
| OCPP20OptionalVariableName
- | OCPP20VendorVariableName;
+ | OCPP20VendorVariableName
type VariableType = {
- name: VariableName;
- instance?: string;
-} & JsonObject;
+ name: VariableName
+ instance?: string
+} & JsonObject
export type OCPP20SetVariableDataType = {
- attributeType?: AttributeEnumType;
- attributeValue: string;
- component: ComponentType;
- variable: VariableType;
-} & JsonObject;
+ attributeType?: AttributeEnumType
+ attributeValue: string
+ component: ComponentType
+ variable: VariableType
+} & JsonObject
enum SetVariableStatusEnumType {
Accepted = 'Accepted',
UnknownComponent = 'UnknownComponent',
UnknownVariable = 'UnknownVariable',
NotSupportedAttributeType = 'NotSupportedAttributeType',
- RebootRequired = 'RebootRequired',
+ RebootRequired = 'RebootRequired'
}
export type OCPP20SetVariableResultType = {
- attributeType?: AttributeEnumType;
- attributeStatus: SetVariableStatusEnumType;
- component: ComponentType;
- variable: VariableType;
- attributeStatusInfo?: StatusInfoType;
-} & JsonObject;
+ attributeType?: AttributeEnumType
+ attributeStatus: SetVariableStatusEnumType
+ component: ComponentType
+ variable: VariableType
+ attributeStatusInfo?: StatusInfoType
+} & JsonObject
export type OCPP20ComponentVariableType = {
- component: ComponentType;
- variable?: VariableType;
-} & JsonObject;
+ component: ComponentType
+ variable?: VariableType
+} & JsonObject
-import { OCPP16ChargePointErrorCode } from './1.6/ChargePointErrorCode.js';
+import { OCPP16ChargePointErrorCode } from './1.6/ChargePointErrorCode.js'
export const ChargePointErrorCode = {
- ...OCPP16ChargePointErrorCode,
-} as const;
-export type ChargePointErrorCode = OCPP16ChargePointErrorCode;
+ ...OCPP16ChargePointErrorCode
+} as const
+// eslint-disable-next-line @typescript-eslint/no-redeclare
+export type ChargePointErrorCode = OCPP16ChargePointErrorCode
OCPP16ChargingProfileKindType,
OCPP16ChargingRateUnitType,
type OCPP16ChargingSchedulePeriod,
- OCPP16RecurrencyKindType,
-} from './1.6/ChargingProfile.js';
+ OCPP16RecurrencyKindType
+} from './1.6/ChargingProfile.js'
-export type ChargingProfile = OCPP16ChargingProfile;
+export type ChargingProfile = OCPP16ChargingProfile
-export type ChargingSchedulePeriod = OCPP16ChargingSchedulePeriod;
+export type ChargingSchedulePeriod = OCPP16ChargingSchedulePeriod
export const ChargingProfileKindType = {
- ...OCPP16ChargingProfileKindType,
-} as const;
-export type ChargingProfileKindType = OCPP16ChargingProfileKindType;
+ ...OCPP16ChargingProfileKindType
+} as const
+// eslint-disable-next-line @typescript-eslint/no-redeclare
+export type ChargingProfileKindType = OCPP16ChargingProfileKindType
export const RecurrencyKindType = {
- ...OCPP16RecurrencyKindType,
-} as const;
-export type RecurrencyKindType = OCPP16RecurrencyKindType;
+ ...OCPP16RecurrencyKindType
+} as const
+// eslint-disable-next-line @typescript-eslint/no-redeclare
+export type RecurrencyKindType = OCPP16RecurrencyKindType
export const ChargingRateUnitType = {
- ...OCPP16ChargingRateUnitType,
-} as const;
-export type ChargingRateUnitType = OCPP16ChargingRateUnitType;
+ ...OCPP16ChargingRateUnitType
+} as const
+// eslint-disable-next-line @typescript-eslint/no-redeclare
+export type ChargingRateUnitType = OCPP16ChargingRateUnitType
-import type { JsonObject } from '../JsonType.js';
+import type { JsonObject } from '../JsonType.js'
export enum GenericStatus {
Accepted = 'Accepted',
- Rejected = 'Rejected',
+ Rejected = 'Rejected'
}
export interface GenericResponse extends JsonObject {
- status: GenericStatus;
+ status: GenericStatus
}
export enum RegistrationStatusEnumType {
ACCEPTED = 'Accepted',
PENDING = 'Pending',
- REJECTED = 'Rejected',
+ REJECTED = 'Rejected'
}
import {
OCPP16StandardParametersKey,
OCPP16SupportedFeatureProfiles,
- OCPP16VendorParametersKey,
-} from './1.6/Configuration.js';
+ OCPP16VendorParametersKey
+} from './1.6/Configuration.js'
import {
OCPP20OptionalVariableName,
OCPP20RequiredVariableName,
- OCPP20VendorVariableName,
-} from './2.0/Variables.js';
-import type { JsonObject } from '../JsonType.js';
+ OCPP20VendorVariableName
+} from './2.0/Variables.js'
+import type { JsonObject } from '../JsonType.js'
export const StandardParametersKey = {
...OCPP16StandardParametersKey,
...OCPP20RequiredVariableName,
- ...OCPP20OptionalVariableName,
-} as const;
-export type StandardParametersKey = OCPP16StandardParametersKey;
+ ...OCPP20OptionalVariableName
+} as const
+// eslint-disable-next-line @typescript-eslint/no-redeclare
+export type StandardParametersKey = OCPP16StandardParametersKey
export const VendorParametersKey = {
...OCPP16VendorParametersKey,
- ...OCPP20VendorVariableName,
-} as const;
-export type VendorParametersKey = OCPP16VendorParametersKey;
+ ...OCPP20VendorVariableName
+} as const
+// eslint-disable-next-line @typescript-eslint/no-redeclare
+export type VendorParametersKey = OCPP16VendorParametersKey
export const SupportedFeatureProfiles = {
- ...OCPP16SupportedFeatureProfiles,
-} as const;
-export type SupportedFeatureProfiles = OCPP16SupportedFeatureProfiles;
+ ...OCPP16SupportedFeatureProfiles
+} as const
+// eslint-disable-next-line @typescript-eslint/no-redeclare
+export type SupportedFeatureProfiles = OCPP16SupportedFeatureProfiles
export enum ConnectorPhaseRotation {
NotApplicable = 'NotApplicable',
SRT = 'SRT',
STR = 'STR',
TRS = 'TRS',
- TSR = 'TSR',
+ TSR = 'TSR'
}
-export type ConfigurationKeyType = string | StandardParametersKey | VendorParametersKey;
+export type ConfigurationKeyType = string | StandardParametersKey | VendorParametersKey
export type OCPPConfigurationKey = {
- key: ConfigurationKeyType;
- readonly: boolean;
- value?: string;
-} & JsonObject;
+ key: ConfigurationKeyType
+ readonly: boolean
+ value?: string
+} & JsonObject
-import { OCPP16ChargePointStatus } from './1.6/ChargePointStatus.js';
-import { OCPP20ConnectorStatusEnumType } from './2.0/Common.js';
+import { OCPP16ChargePointStatus } from './1.6/ChargePointStatus.js'
+import { OCPP20ConnectorStatusEnumType } from './2.0/Common.js'
export const ConnectorStatusEnum = {
...OCPP16ChargePointStatus,
- ...OCPP20ConnectorStatusEnumType,
-} as const;
-export type ConnectorStatusEnum = OCPP16ChargePointStatus | OCPP20ConnectorStatusEnumType;
+ ...OCPP20ConnectorStatusEnumType
+} as const
+// eslint-disable-next-line @typescript-eslint/no-redeclare
+export type ConnectorStatusEnum = OCPP16ChargePointStatus | OCPP20ConnectorStatusEnumType
export type ConnectorStatusTransition = Readonly<{
- from?: ConnectorStatusEnum;
- to: ConnectorStatusEnum;
-}>;
+ from?: ConnectorStatusEnum
+ to: ConnectorStatusEnum
+}>
// Payload for Action is syntactically correct but at least one of the fields violates data type constraints (e.g. "somestring" = 12)
TYPE_CONSTRAINT_VIOLATION = 'TypeConstraintViolation',
// Any other error not covered by the previous ones
- GENERIC_ERROR = 'GenericError',
+ GENERIC_ERROR = 'GenericError'
}
export enum MessageType {
CALL_MESSAGE = 2, // Caller to Callee
CALL_RESULT_MESSAGE = 3, // Callee to Caller
- CALL_ERROR_MESSAGE = 4, // Callee to Caller
+ CALL_ERROR_MESSAGE = 4 // Callee to Caller
}
OCPP16MeterValueMeasurand,
OCPP16MeterValuePhase,
OCPP16MeterValueUnit,
- type OCPP16SampledValue,
-} from './1.6/MeterValues.js';
+ type OCPP16SampledValue
+} from './1.6/MeterValues.js'
export const MeterValueUnit = {
- ...OCPP16MeterValueUnit,
-} as const;
-export type MeterValueUnit = OCPP16MeterValueUnit;
+ ...OCPP16MeterValueUnit
+} as const
+// eslint-disable-next-line @typescript-eslint/no-redeclare
+export type MeterValueUnit = OCPP16MeterValueUnit
export const MeterValueContext = {
- ...OCPP16MeterValueContext,
-} as const;
-export type MeterValueContext = OCPP16MeterValueContext;
+ ...OCPP16MeterValueContext
+} as const
+// eslint-disable-next-line @typescript-eslint/no-redeclare
+export type MeterValueContext = OCPP16MeterValueContext
export const MeterValueMeasurand = {
- ...OCPP16MeterValueMeasurand,
-} as const;
-export type MeterValueMeasurand = OCPP16MeterValueMeasurand;
+ ...OCPP16MeterValueMeasurand
+} as const
+// eslint-disable-next-line @typescript-eslint/no-redeclare
+export type MeterValueMeasurand = OCPP16MeterValueMeasurand
export const MeterValueLocation = {
- ...OCPP16MeterValueLocation,
-} as const;
-export type MeterValueLocation = OCPP16MeterValueLocation;
+ ...OCPP16MeterValueLocation
+} as const
+// eslint-disable-next-line @typescript-eslint/no-redeclare
+export type MeterValueLocation = OCPP16MeterValueLocation
export const MeterValuePhase = {
- ...OCPP16MeterValuePhase,
-} as const;
-export type MeterValuePhase = OCPP16MeterValuePhase;
+ ...OCPP16MeterValuePhase
+} as const
+// eslint-disable-next-line @typescript-eslint/no-redeclare
+export type MeterValuePhase = OCPP16MeterValuePhase
-export type SampledValue = OCPP16SampledValue;
+export type SampledValue = OCPP16SampledValue
-export type MeterValue = OCPP16MeterValue;
+export type MeterValue = OCPP16MeterValue
export enum OCPPProtocol {
- JSON = 'json',
+ JSON = 'json'
}
export enum OCPPVersion {
VERSION_16 = '1.6',
VERSION_20 = '2.0',
- VERSION_201 = '2.0.1',
+ VERSION_201 = '2.0.1'
}
-import { OCPP16DiagnosticsStatus } from './1.6/DiagnosticsStatus.js';
-import type { OCPP16MeterValuesRequest } from './1.6/MeterValues.js';
+import { OCPP16DiagnosticsStatus } from './1.6/DiagnosticsStatus.js'
+import type { OCPP16MeterValuesRequest } from './1.6/MeterValues.js'
import {
OCPP16AvailabilityType,
type OCPP16BootNotificationRequest,
OCPP16MessageTrigger,
OCPP16RequestCommand,
type OCPP16ReserveNowRequest,
- type OCPP16StatusNotificationRequest,
-} from './1.6/Requests.js';
-import { OperationalStatusEnumType } from './2.0/Common.js';
+ type OCPP16StatusNotificationRequest
+} from './1.6/Requests.js'
+import { OperationalStatusEnumType } from './2.0/Common.js'
import {
type OCPP20BootNotificationRequest,
OCPP20IncomingRequestCommand,
OCPP20RequestCommand,
- type OCPP20StatusNotificationRequest,
-} from './2.0/Requests.js';
-import type { MessageType } from './MessageType.js';
-import type { ChargingStation } from '../../charging-station/index.js';
-import type { OCPPError } from '../../exception/index.js';
-import type { JsonType } from '../JsonType.js';
+ type OCPP20StatusNotificationRequest
+} from './2.0/Requests.js'
+import type { MessageType } from './MessageType.js'
+import type { ChargingStation } from '../../charging-station/index.js'
+import type { OCPPError } from '../../exception/index.js'
+import type { JsonType } from '../JsonType.js'
export const RequestCommand = {
...OCPP16RequestCommand,
- ...OCPP20RequestCommand,
-} as const;
-export type RequestCommand = OCPP16RequestCommand | OCPP20RequestCommand;
+ ...OCPP20RequestCommand
+} as const
+// eslint-disable-next-line @typescript-eslint/no-redeclare
+export type RequestCommand = OCPP16RequestCommand | OCPP20RequestCommand
-export type OutgoingRequest = [MessageType.CALL_MESSAGE, string, RequestCommand, JsonType];
+export type OutgoingRequest = [MessageType.CALL_MESSAGE, string, RequestCommand, JsonType]
export interface RequestParams {
- skipBufferingOnError?: boolean;
- triggerMessage?: boolean;
- throwError?: boolean;
+ skipBufferingOnError?: boolean
+ triggerMessage?: boolean
+ throwError?: boolean
}
export const IncomingRequestCommand = {
...OCPP16IncomingRequestCommand,
- ...OCPP20IncomingRequestCommand,
-} as const;
-export type IncomingRequestCommand = OCPP16IncomingRequestCommand | OCPP20IncomingRequestCommand;
+ ...OCPP20IncomingRequestCommand
+} as const
+// eslint-disable-next-line @typescript-eslint/no-redeclare
+export type IncomingRequestCommand = OCPP16IncomingRequestCommand | OCPP20IncomingRequestCommand
-export type IncomingRequest = [MessageType.CALL_MESSAGE, string, IncomingRequestCommand, JsonType];
+export type IncomingRequest = [MessageType.CALL_MESSAGE, string, IncomingRequestCommand, JsonType]
export type IncomingRequestHandler = (
chargingStation: ChargingStation,
- commandPayload: JsonType,
-) => JsonType | Promise<JsonType>;
+ commandPayload: JsonType
+) => JsonType | Promise<JsonType>
-export type ResponseCallback = (payload: JsonType, requestPayload: JsonType) => void;
+export type ResponseCallback = (payload: JsonType, requestPayload: JsonType) => void
-export type ErrorCallback = (ocppError: OCPPError, requestStatistic?: boolean) => void;
+export type ErrorCallback = (ocppError: OCPPError, requestStatistic?: boolean) => void
export type CachedRequest = [
ResponseCallback,
ErrorCallback,
RequestCommand | IncomingRequestCommand,
- JsonType,
-];
+ JsonType
+]
export const MessageTrigger = {
- ...OCPP16MessageTrigger,
-} as const;
-export type MessageTrigger = OCPP16MessageTrigger;
+ ...OCPP16MessageTrigger
+} as const
+// eslint-disable-next-line @typescript-eslint/no-redeclare
+export type MessageTrigger = OCPP16MessageTrigger
-export type BootNotificationRequest = OCPP16BootNotificationRequest | OCPP20BootNotificationRequest;
+export type BootNotificationRequest = OCPP16BootNotificationRequest | OCPP20BootNotificationRequest
-export type HeartbeatRequest = OCPP16HeartbeatRequest;
+export type HeartbeatRequest = OCPP16HeartbeatRequest
export type StatusNotificationRequest =
| OCPP16StatusNotificationRequest
- | OCPP20StatusNotificationRequest;
+ | OCPP20StatusNotificationRequest
-export type MeterValuesRequest = OCPP16MeterValuesRequest;
+export type MeterValuesRequest = OCPP16MeterValuesRequest
-export type DataTransferRequest = OCPP16DataTransferRequest;
+export type DataTransferRequest = OCPP16DataTransferRequest
-export type DiagnosticsStatusNotificationRequest = OCPP16DiagnosticsStatusNotificationRequest;
+export type DiagnosticsStatusNotificationRequest = OCPP16DiagnosticsStatusNotificationRequest
-export type FirmwareStatusNotificationRequest = OCPP16FirmwareStatusNotificationRequest;
+export type FirmwareStatusNotificationRequest = OCPP16FirmwareStatusNotificationRequest
export const AvailabilityType = {
...OCPP16AvailabilityType,
- ...OperationalStatusEnumType,
-} as const;
-export type AvailabilityType = OCPP16AvailabilityType | OperationalStatusEnumType;
+ ...OperationalStatusEnumType
+} as const
+// eslint-disable-next-line @typescript-eslint/no-redeclare
+export type AvailabilityType = OCPP16AvailabilityType | OperationalStatusEnumType
export const DiagnosticsStatus = {
- ...OCPP16DiagnosticsStatus,
-} as const;
-export type DiagnosticsStatus = OCPP16DiagnosticsStatus;
+ ...OCPP16DiagnosticsStatus
+} as const
+// eslint-disable-next-line @typescript-eslint/no-redeclare
+export type DiagnosticsStatus = OCPP16DiagnosticsStatus
export const FirmwareStatus = {
- ...OCPP16FirmwareStatus,
-} as const;
-export type FirmwareStatus = OCPP16FirmwareStatus;
+ ...OCPP16FirmwareStatus
+} as const
+// eslint-disable-next-line @typescript-eslint/no-redeclare
+export type FirmwareStatus = OCPP16FirmwareStatus
-export type ResponseType = JsonType | OCPPError;
+export type ResponseType = JsonType | OCPPError
-export type ReserveNowRequest = OCPP16ReserveNowRequest;
+export type ReserveNowRequest = OCPP16ReserveNowRequest
-export type CancelReservationRequest = OCPP16CancelReservationRequest;
+export type CancelReservationRequest = OCPP16CancelReservationRequest
-import type { OCPP16ReserveNowRequest } from './1.6/Requests.js';
+import type { OCPP16ReserveNowRequest } from './1.6/Requests.js'
-export type Reservation = OCPP16ReserveNowRequest;
+export type Reservation = OCPP16ReserveNowRequest
-export type ReservationKey = keyof Reservation;
+export type ReservationKey = keyof Reservation
export enum ReservationTerminationReason {
EXPIRED = 'Expired',
TRANSACTION_STARTED = 'TransactionStarted',
CONNECTOR_STATE_CHANGED = 'ConnectorStateChanged',
RESERVATION_CANCELED = 'ReservationCanceled',
- REPLACE_EXISTING = 'ReplaceExisting',
+ REPLACE_EXISTING = 'ReplaceExisting'
}
-import type { OCPP16MeterValuesResponse } from './1.6/MeterValues.js';
+import type { OCPP16MeterValuesResponse } from './1.6/MeterValues.js'
import {
OCPP16AvailabilityStatus,
type OCPP16BootNotificationResponse,
OCPP16ReservationStatus,
type OCPP16StatusNotificationResponse,
OCPP16TriggerMessageStatus,
- OCPP16UnlockStatus,
-} from './1.6/Responses.js';
-import type { OCPP20BootNotificationResponse, OCPP20ClearCacheResponse } from './2.0/Responses.js';
-import { type GenericResponse, GenericStatus } from './Common.js';
-import type { ErrorType } from './ErrorType.js';
-import type { MessageType } from './MessageType.js';
-import type { ChargingStation } from '../../charging-station/index.js';
-import type { JsonType } from '../JsonType.js';
+ OCPP16UnlockStatus
+} from './1.6/Responses.js'
+import type { OCPP20BootNotificationResponse, OCPP20ClearCacheResponse } from './2.0/Responses.js'
+import { type GenericResponse, GenericStatus } from './Common.js'
+import type { ErrorType } from './ErrorType.js'
+import type { MessageType } from './MessageType.js'
+import type { ChargingStation } from '../../charging-station/index.js'
+import type { JsonType } from '../JsonType.js'
-export type Response = [MessageType.CALL_RESULT_MESSAGE, string, JsonType];
+export type Response = [MessageType.CALL_RESULT_MESSAGE, string, JsonType]
-export type ErrorResponse = [MessageType.CALL_ERROR_MESSAGE, string, ErrorType, string, JsonType];
+export type ErrorResponse = [MessageType.CALL_ERROR_MESSAGE, string, ErrorType, string, JsonType]
export type ResponseHandler = (
chargingStation: ChargingStation,
payload: JsonType,
- requestPayload?: JsonType,
-) => void | Promise<void>;
+ requestPayload?: JsonType
+) => void | Promise<void>
export type BootNotificationResponse =
| OCPP16BootNotificationResponse
- | OCPP20BootNotificationResponse;
+ | OCPP20BootNotificationResponse
-export type HeartbeatResponse = OCPP16HeartbeatResponse;
+export type HeartbeatResponse = OCPP16HeartbeatResponse
-export type ClearCacheResponse = GenericResponse | OCPP20ClearCacheResponse;
+export type ClearCacheResponse = GenericResponse | OCPP20ClearCacheResponse
-export type StatusNotificationResponse = OCPP16StatusNotificationResponse;
+export type StatusNotificationResponse = OCPP16StatusNotificationResponse
-export type MeterValuesResponse = OCPP16MeterValuesResponse;
+export type MeterValuesResponse = OCPP16MeterValuesResponse
-export type DataTransferResponse = OCPP16DataTransferResponse;
+export type DataTransferResponse = OCPP16DataTransferResponse
-export type DiagnosticsStatusNotificationResponse = OCPP16DiagnosticsStatusNotificationResponse;
+export type DiagnosticsStatusNotificationResponse = OCPP16DiagnosticsStatusNotificationResponse
-export type FirmwareStatusNotificationResponse = OCPP16FirmwareStatusNotificationResponse;
+export type FirmwareStatusNotificationResponse = OCPP16FirmwareStatusNotificationResponse
export const AvailabilityStatus = {
- ...OCPP16AvailabilityStatus,
-} as const;
-export type AvailabilityStatus = OCPP16AvailabilityStatus;
+ ...OCPP16AvailabilityStatus
+} as const
+// eslint-disable-next-line @typescript-eslint/no-redeclare
+export type AvailabilityStatus = OCPP16AvailabilityStatus
export const ChargingProfileStatus = {
- ...OCPP16ChargingProfileStatus,
-} as const;
-export type ChargingProfileStatus = OCPP16ChargingProfileStatus;
+ ...OCPP16ChargingProfileStatus
+} as const
+// eslint-disable-next-line @typescript-eslint/no-redeclare
+export type ChargingProfileStatus = OCPP16ChargingProfileStatus
export const ClearChargingProfileStatus = {
- ...OCPP16ClearChargingProfileStatus,
-} as const;
-export type ClearChargingProfileStatus = OCPP16ClearChargingProfileStatus;
+ ...OCPP16ClearChargingProfileStatus
+} as const
+// eslint-disable-next-line @typescript-eslint/no-redeclare
+export type ClearChargingProfileStatus = OCPP16ClearChargingProfileStatus
export const ConfigurationStatus = {
- ...OCPP16ConfigurationStatus,
-} as const;
-export type ConfigurationStatus = OCPP16ConfigurationStatus;
+ ...OCPP16ConfigurationStatus
+} as const
+// eslint-disable-next-line @typescript-eslint/no-redeclare
+export type ConfigurationStatus = OCPP16ConfigurationStatus
export const UnlockStatus = {
- ...OCPP16UnlockStatus,
-} as const;
-export type UnlockStatus = OCPP16UnlockStatus;
+ ...OCPP16UnlockStatus
+} as const
+// eslint-disable-next-line @typescript-eslint/no-redeclare
+export type UnlockStatus = OCPP16UnlockStatus
export const TriggerMessageStatus = {
- ...OCPP16TriggerMessageStatus,
-} as const;
-export type TriggerMessageStatus = OCPP16TriggerMessageStatus;
+ ...OCPP16TriggerMessageStatus
+} as const
+// eslint-disable-next-line @typescript-eslint/no-redeclare
+export type TriggerMessageStatus = OCPP16TriggerMessageStatus
export const DataTransferStatus = {
- ...OCPP16DataTransferStatus,
-} as const;
-export type DataTransferStatus = OCPP16DataTransferStatus;
+ ...OCPP16DataTransferStatus
+} as const
+// eslint-disable-next-line @typescript-eslint/no-redeclare
+export type DataTransferStatus = OCPP16DataTransferStatus
-export type ReservationStatus = OCPP16ReservationStatus;
+export type ReservationStatus = OCPP16ReservationStatus
+// eslint-disable-next-line @typescript-eslint/no-redeclare
export const ReservationStatus = {
- ...OCPP16ReservationStatus,
-} as const;
+ ...OCPP16ReservationStatus
+} as const
-export type CancelReservationStatus = GenericStatus;
+export type CancelReservationStatus = GenericStatus
+// eslint-disable-next-line @typescript-eslint/no-redeclare
export const CancelReservationStatus = {
- ...GenericStatus,
-} as const;
+ ...GenericStatus
+} as const
-export type CancelReservationResponse = GenericResponse;
+export type CancelReservationResponse = GenericResponse
type OCPP16StartTransactionResponse,
OCPP16StopTransactionReason,
type OCPP16StopTransactionRequest,
- type OCPP16StopTransactionResponse,
-} from './1.6/Transaction.js';
+ type OCPP16StopTransactionResponse
+} from './1.6/Transaction.js'
export const AuthorizationStatus = {
- ...OCPP16AuthorizationStatus,
-} as const;
-export type AuthorizationStatus = OCPP16AuthorizationStatus;
+ ...OCPP16AuthorizationStatus
+} as const
+// eslint-disable-next-line @typescript-eslint/no-redeclare
+export type AuthorizationStatus = OCPP16AuthorizationStatus
-export type AuthorizeRequest = OCPP16AuthorizeRequest;
+export type AuthorizeRequest = OCPP16AuthorizeRequest
-export type AuthorizeResponse = OCPP16AuthorizeResponse;
+export type AuthorizeResponse = OCPP16AuthorizeResponse
export const StopTransactionReason = {
- ...OCPP16StopTransactionReason,
-} as const;
-export type StopTransactionReason = OCPP16StopTransactionReason;
+ ...OCPP16StopTransactionReason
+} as const
+// eslint-disable-next-line @typescript-eslint/no-redeclare
+export type StopTransactionReason = OCPP16StopTransactionReason
-export type StartTransactionRequest = OCPP16StartTransactionRequest;
+export type StartTransactionRequest = OCPP16StartTransactionRequest
-export type StartTransactionResponse = OCPP16StartTransactionResponse;
+export type StartTransactionResponse = OCPP16StartTransactionResponse
-export type StopTransactionRequest = OCPP16StopTransactionRequest;
+export type StopTransactionRequest = OCPP16StopTransactionRequest
-export type StopTransactionResponse = OCPP16StopTransactionResponse;
+export type StopTransactionResponse = OCPP16StopTransactionResponse
// eslint-disable-next-line @typescript-eslint/no-unused-vars
-import { Entity, ManyToOne, PrimaryKey, Property } from '@mikro-orm/core';
+import { Entity, ManyToOne, PrimaryKey, Property } from '@mikro-orm/core'
// eslint-disable-next-line @typescript-eslint/no-unused-vars
-import type { PerformanceRecord } from './PerformanceRecord.js';
+import type { PerformanceRecord } from './PerformanceRecord.js'
@Entity()
export class PerformanceData {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
-import { Collection, Entity, OneToMany, PrimaryKey, Property } from '@mikro-orm/core';
+import { Collection, Entity, OneToMany, PrimaryKey, Property } from '@mikro-orm/core'
// eslint-disable-next-line @typescript-eslint/no-unused-vars
-import type { PerformanceData } from './PerformanceData.js';
+import type { PerformanceData } from './PerformanceData.js'
@Entity()
export class PerformanceRecord {
// Partial Copyright Jerome Benoit. 2021-2023. All Rights Reserved.
-import { Queue } from 'mnemonist';
+import { Queue } from 'mnemonist'
-import { Constants } from './Constants.js';
+import { Constants } from './Constants.js'
export enum AsyncLockType {
configuration = 'configuration',
- performance = 'performance',
+ performance = 'performance'
}
-type ResolveType = (value: void | PromiseLike<void>) => void;
+type ResolveType = (value: void | PromiseLike<void>) => void
export class AsyncLock {
- private static readonly asyncLocks = new Map<AsyncLockType, AsyncLock>();
- private acquired: boolean;
- private readonly resolveQueue: Queue<ResolveType>;
+ private static readonly asyncLocks = new Map<AsyncLockType, AsyncLock>()
+ private acquired: boolean
+ private readonly resolveQueue: Queue<ResolveType>
- private constructor() {
- this.acquired = false;
- this.resolveQueue = new Queue<ResolveType>();
+ private constructor () {
+ this.acquired = false
+ this.resolveQueue = new Queue<ResolveType>()
}
public static async runExclusive<T>(type: AsyncLockType, fn: () => T | Promise<T>): Promise<T> {
- return AsyncLock.acquire(type)
+ return await AsyncLock.acquire(type)
.then(fn)
.finally(() => {
- AsyncLock.release(type).catch(Constants.EMPTY_FUNCTION);
- });
+ AsyncLock.release(type).catch(Constants.EMPTY_FUNCTION)
+ })
}
- private static async acquire(type: AsyncLockType): Promise<void> {
- const asyncLock = AsyncLock.getAsyncLock(type);
+ private static async acquire (type: AsyncLockType): Promise<void> {
+ const asyncLock = AsyncLock.getAsyncLock(type)
if (!asyncLock.acquired) {
- asyncLock.acquired = true;
- return;
+ asyncLock.acquired = true
+ return
}
- return new Promise<void>((resolve) => {
- asyncLock.resolveQueue.enqueue(resolve);
- });
+ await new Promise<void>((resolve) => {
+ asyncLock.resolveQueue.enqueue(resolve)
+ })
}
- private static async release(type: AsyncLockType): Promise<void> {
- const asyncLock = AsyncLock.getAsyncLock(type);
+ private static async release (type: AsyncLockType): Promise<void> {
+ const asyncLock = AsyncLock.getAsyncLock(type)
if (asyncLock.resolveQueue.size === 0 && asyncLock.acquired) {
- asyncLock.acquired = false;
- return;
+ asyncLock.acquired = false
+ return
}
- const queuedResolve = asyncLock.resolveQueue.dequeue()!;
- return new Promise<void>((resolve) => {
- queuedResolve();
- resolve();
- });
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ const queuedResolve = asyncLock.resolveQueue.dequeue()!
+ await new Promise<void>((resolve) => {
+ queuedResolve()
+ resolve()
+ })
}
- private static getAsyncLock(type: AsyncLockType): AsyncLock {
+ private static getAsyncLock (type: AsyncLockType): AsyncLock {
if (!AsyncLock.asyncLocks.has(type)) {
- AsyncLock.asyncLocks.set(type, new AsyncLock());
+ AsyncLock.asyncLocks.set(type, new AsyncLock())
}
- return AsyncLock.asyncLocks.get(type)!;
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ return AsyncLock.asyncLocks.get(type)!
}
}
-import { isNullOrUndefined } from './Utils.js';
-import type { ChargingStation } from '../charging-station/index.js';
+import { isNullOrUndefined } from './Utils.js'
+import type { ChargingStation } from '../charging-station/index.js'
import type {
ChargingStationAutomaticTransactionGeneratorConfiguration,
ConnectorStatus,
EvseStatusConfiguration,
- EvseStatusWorkerType,
-} from '../types/index.js';
+ EvseStatusWorkerType
+} from '../types/index.js'
export const buildChargingStationAutomaticTransactionGeneratorConfiguration = (
- chargingStation: ChargingStation,
+ chargingStation: ChargingStation
): ChargingStationAutomaticTransactionGeneratorConfiguration => {
return {
automaticTransactionGenerator: chargingStation.getAutomaticTransactionGeneratorConfiguration(),
...(!isNullOrUndefined(chargingStation.automaticTransactionGenerator?.connectorsStatus) && {
automaticTransactionGeneratorStatuses: [
- ...chargingStation.automaticTransactionGenerator!.connectorsStatus.values(),
- ],
- }),
- };
-};
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ ...chargingStation.automaticTransactionGenerator!.connectorsStatus.values()
+ ]
+ })
+ }
+}
export const buildConnectorsStatus = (chargingStation: ChargingStation): ConnectorStatus[] => {
return [...chargingStation.connectors.values()].map(
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
- ({ transactionSetInterval, ...connectorStatusRest }) => connectorStatusRest,
- );
-};
+ ({ transactionSetInterval, ...connectorStatusRest }) => connectorStatusRest
+ )
+}
export const enum OutputFormat {
configuration = 'configuration',
- worker = 'worker',
+ worker = 'worker'
}
export const buildEvsesStatus = (
chargingStation: ChargingStation,
- outputFormat: OutputFormat = OutputFormat.configuration,
-): (EvseStatusWorkerType | EvseStatusConfiguration)[] => {
+ outputFormat: OutputFormat = OutputFormat.configuration
+): Array<EvseStatusWorkerType | EvseStatusConfiguration> => {
+ // eslint-disable-next-line array-callback-return
return [...chargingStation.evses.values()].map((evseStatus) => {
const connectorsStatus = [...evseStatus.connectors.values()].map(
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
- ({ transactionSetInterval, ...connectorStatusRest }) => connectorStatusRest,
- );
- let status: EvseStatusConfiguration;
+ ({ transactionSetInterval, ...connectorStatusRest }) => connectorStatusRest
+ )
+ let status: EvseStatusConfiguration
switch (outputFormat) {
case OutputFormat.worker:
return {
...evseStatus,
- connectors: connectorsStatus,
- };
+ connectors: connectorsStatus
+ }
case OutputFormat.configuration:
status = {
...evseStatus,
- connectorsStatus,
- };
- delete (status as EvseStatusWorkerType).connectors;
- return status;
+ connectorsStatus
+ }
+ delete (status as EvseStatusWorkerType).connectors
+ return status
}
- });
-};
+ })
+}
// Copyright Jerome Benoit. 2021-2023. All Rights Reserved.
-export const DEFAULT_CIRCULAR_ARRAY_SIZE = 1024;
+export const DEFAULT_CIRCULAR_ARRAY_SIZE = 1024
/**
* Array with a maximum length and shifting items when full.
*/
export class CircularArray<T> extends Array<T> {
- public size: number;
+ public size: number
- constructor(size: number = DEFAULT_CIRCULAR_ARRAY_SIZE, ...items: T[]) {
- super();
- this.checkSize(size);
- this.size = size;
+ constructor (size: number = DEFAULT_CIRCULAR_ARRAY_SIZE, ...items: T[]) {
+ super()
+ this.checkSize(size)
+ this.size = size
if (arguments.length > 1) {
- this.push(...items);
+ this.push(...items)
}
}
- public push(...items: T[]): number {
- const length = super.push(...items);
+ public push (...items: T[]): number {
+ const length = super.push(...items)
if (length > this.size) {
- super.splice(0, length - this.size);
+ super.splice(0, length - this.size)
}
- return this.length;
+ return this.length
}
- public unshift(...items: T[]): number {
- const length = super.unshift(...items);
+ public unshift (...items: T[]): number {
+ const length = super.unshift(...items)
if (length > this.size) {
- super.splice(this.size, items.length);
+ super.splice(this.size, items.length)
}
- return this.length;
+ return this.length
}
- public concat(...items: (T | ConcatArray<T>)[]): CircularArray<T> {
- const concatenatedCircularArray = super.concat(items as T[]) as CircularArray<T>;
- concatenatedCircularArray.size = this.size;
+ public concat (...items: Array<T | ConcatArray<T>>): CircularArray<T> {
+ const concatenatedCircularArray = super.concat(items as T[]) as CircularArray<T>
+ concatenatedCircularArray.size = this.size
if (concatenatedCircularArray.length > concatenatedCircularArray.size) {
concatenatedCircularArray.splice(
0,
- concatenatedCircularArray.length - concatenatedCircularArray.size,
- );
+ concatenatedCircularArray.length - concatenatedCircularArray.size
+ )
}
- return concatenatedCircularArray;
+ return concatenatedCircularArray
}
- public splice(start: number, deleteCount?: number, ...items: T[]): CircularArray<T> {
- let itemsRemoved: T[] = [];
+ public splice (start: number, deleteCount?: number, ...items: T[]): CircularArray<T> {
+ let itemsRemoved: T[] = []
if (arguments.length >= 3 && deleteCount !== undefined) {
- itemsRemoved = super.splice(start, deleteCount, ...items);
+ itemsRemoved = super.splice(start, deleteCount, ...items)
if (this.length > this.size) {
- const itemsOverflowing = super.splice(0, this.length - this.size);
+ const itemsOverflowing = super.splice(0, this.length - this.size)
itemsRemoved = new CircularArray<T>(
itemsRemoved.length + itemsOverflowing.length,
...itemsRemoved,
- ...itemsOverflowing,
- );
+ ...itemsOverflowing
+ )
}
} else if (arguments.length === 2) {
- itemsRemoved = super.splice(start, deleteCount);
+ itemsRemoved = super.splice(start, deleteCount)
} else {
- itemsRemoved = super.splice(start);
+ itemsRemoved = super.splice(start)
}
- return itemsRemoved as CircularArray<T>;
+ return itemsRemoved as CircularArray<T>
}
- public resize(size: number): void {
- this.checkSize(size);
+ public resize (size: number): void {
+ this.checkSize(size)
if (size === 0) {
- this.length = 0;
+ this.length = 0
} else if (size < this.size) {
for (let i = size; i < this.size; i++) {
- super.pop();
+ super.pop()
}
}
- this.size = size;
+ this.size = size
}
- public empty(): boolean {
- return this.length === 0;
+ public empty (): boolean {
+ return this.length === 0
}
- public full(): boolean {
- return this.length === this.size;
+ public full (): boolean {
+ return this.length === this.size
}
- private checkSize(size: number): void {
+ private checkSize (size: number): void {
if (!Number.isSafeInteger(size)) {
- throw new TypeError(`Invalid circular array size: ${size} is not a safe integer`);
+ throw new TypeError(`Invalid circular array size: ${size} is not a safe integer`)
}
if (size < 0) {
- throw new RangeError(`Invalid circular array size: ${size} < 0`);
+ throw new RangeError(`Invalid circular array size: ${size} < 0`)
}
}
}
-import { type FSWatcher, readFileSync, watch } from 'node:fs';
-import { dirname, join } from 'node:path';
-import { env } from 'node:process';
-import { fileURLToPath } from 'node:url';
+import { type FSWatcher, readFileSync, watch } from 'node:fs'
+import { dirname, join } from 'node:path'
+import { env } from 'node:process'
+import { fileURLToPath } from 'node:url'
-import chalk from 'chalk';
-import merge from 'just-merge';
+import chalk from 'chalk'
+import merge from 'just-merge'
import {
buildPerformanceUriFilePath,
checkWorkerProcessType,
getDefaultPerformanceStorageUri,
handleFileException,
- logPrefix,
-} from './ConfigurationUtils.js';
-import { Constants } from './Constants.js';
-import { hasOwnProp, isCFEnvironment, isUndefined, once } from './Utils.js';
+ logPrefix
+} from './ConfigurationUtils.js'
+import { Constants } from './Constants.js'
+import { hasOwnProp, isCFEnvironment, isUndefined, once } from './Utils.js'
import {
ApplicationProtocol,
type ConfigurationData,
StorageType,
SupervisionUrlDistribution,
type UIServerConfiguration,
- type WorkerConfiguration,
-} from '../types/index.js';
+ type WorkerConfiguration
+} from '../types/index.js'
import {
DEFAULT_ELEMENT_START_DELAY,
DEFAULT_POOL_MAX_SIZE,
DEFAULT_POOL_MIN_SIZE,
DEFAULT_WORKER_START_DELAY,
- WorkerProcessType,
-} from '../worker/index.js';
+ WorkerProcessType
+} from '../worker/index.js'
type ConfigurationSectionType =
| LogConfiguration
| StorageConfiguration
| WorkerConfiguration
- | UIServerConfiguration;
+ | UIServerConfiguration
+// eslint-disable-next-line @typescript-eslint/no-extraneous-class
export class Configuration {
- public static configurationChangeCallback: () => Promise<void>;
+ public static configurationChangeCallback: () => Promise<void>
- private static configurationFile = join(
+ private static readonly configurationFile = join(
dirname(fileURLToPath(import.meta.url)),
'assets',
- 'config.json',
- );
+ 'config.json'
+ )
- private static configurationFileReloading = false;
- private static configurationData?: ConfigurationData;
- private static configurationFileWatcher?: FSWatcher;
- private static configurationSectionCache = new Map<
- ConfigurationSection,
- ConfigurationSectionType
+ private static configurationFileReloading = false
+ private static configurationData?: ConfigurationData
+ private static configurationFileWatcher?: FSWatcher
+ private static readonly configurationSectionCache = new Map<
+ ConfigurationSection,
+ ConfigurationSectionType
>([
[ConfigurationSection.log, Configuration.buildLogSection()],
[ConfigurationSection.performanceStorage, Configuration.buildPerformanceStorageSection()],
[ConfigurationSection.worker, Configuration.buildWorkerSection()],
- [ConfigurationSection.uiServer, Configuration.buildUIServerSection()],
- ]);
+ [ConfigurationSection.uiServer, Configuration.buildUIServerSection()]
+ ])
- private constructor() {
+ private constructor () {
// This is intentional
}
public static getConfigurationSection<T extends ConfigurationSectionType>(
- sectionName: ConfigurationSection,
+ sectionName: ConfigurationSection
): T {
if (!Configuration.isConfigurationSectionCached(sectionName)) {
- Configuration.cacheConfigurationSection(sectionName);
+ Configuration.cacheConfigurationSection(sectionName)
}
- return Configuration.configurationSectionCache.get(sectionName) as T;
+ return Configuration.configurationSectionCache.get(sectionName) as T
}
- public static getStationTemplateUrls(): StationTemplateUrl[] | undefined {
+ public static getStationTemplateUrls (): StationTemplateUrl[] | undefined {
const checkDeprecatedConfigurationKeysOnce = once(
Configuration.checkDeprecatedConfigurationKeys.bind(Configuration),
- Configuration,
- );
- checkDeprecatedConfigurationKeysOnce();
- return Configuration.getConfigurationData()?.stationTemplateUrls;
+ Configuration
+ )
+ checkDeprecatedConfigurationKeysOnce()
+ return Configuration.getConfigurationData()?.stationTemplateUrls
}
- public static getSupervisionUrls(): string | string[] | undefined {
+ public static getSupervisionUrls (): string | string[] | undefined {
if (
!isUndefined(
- Configuration.getConfigurationData()?.['supervisionURLs' as keyof ConfigurationData],
+ Configuration.getConfigurationData()?.['supervisionURLs' as keyof ConfigurationData]
)
) {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
Configuration.getConfigurationData()!.supervisionUrls = Configuration.getConfigurationData()![
'supervisionURLs' as keyof ConfigurationData
- ] as string | string[];
+ ] as string | string[]
}
- return Configuration.getConfigurationData()?.supervisionUrls;
+ return Configuration.getConfigurationData()?.supervisionUrls
}
- public static getSupervisionUrlDistribution(): SupervisionUrlDistribution | undefined {
+ public static getSupervisionUrlDistribution (): SupervisionUrlDistribution | undefined {
return hasOwnProp(Configuration.getConfigurationData(), 'supervisionUrlDistribution')
? Configuration.getConfigurationData()?.supervisionUrlDistribution
- : SupervisionUrlDistribution.ROUND_ROBIN;
+ : SupervisionUrlDistribution.ROUND_ROBIN
}
- public static workerPoolInUse(): boolean {
+ public static workerPoolInUse (): boolean {
return [WorkerProcessType.dynamicPool, WorkerProcessType.fixedPool].includes(
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
Configuration.getConfigurationSection<WorkerConfiguration>(ConfigurationSection.worker)
- .processType!,
- );
+ .processType!
+ )
}
- public static workerDynamicPoolInUse(): boolean {
+ public static workerDynamicPoolInUse (): boolean {
return (
Configuration.getConfigurationSection<WorkerConfiguration>(ConfigurationSection.worker)
.processType === WorkerProcessType.dynamicPool
- );
+ )
}
- private static isConfigurationSectionCached(sectionName: ConfigurationSection): boolean {
- return Configuration.configurationSectionCache.has(sectionName);
+ private static isConfigurationSectionCached (sectionName: ConfigurationSection): boolean {
+ return Configuration.configurationSectionCache.has(sectionName)
}
- private static cacheConfigurationSection(sectionName: ConfigurationSection): void {
+ private static cacheConfigurationSection (sectionName: ConfigurationSection): void {
switch (sectionName) {
case ConfigurationSection.log:
- Configuration.configurationSectionCache.set(sectionName, Configuration.buildLogSection());
- break;
+ Configuration.configurationSectionCache.set(sectionName, Configuration.buildLogSection())
+ break
case ConfigurationSection.performanceStorage:
Configuration.configurationSectionCache.set(
sectionName,
- Configuration.buildPerformanceStorageSection(),
- );
- break;
+ Configuration.buildPerformanceStorageSection()
+ )
+ break
case ConfigurationSection.worker:
- Configuration.configurationSectionCache.set(
- sectionName,
- Configuration.buildWorkerSection(),
- );
- break;
+ Configuration.configurationSectionCache.set(sectionName, Configuration.buildWorkerSection())
+ break
case ConfigurationSection.uiServer:
Configuration.configurationSectionCache.set(
sectionName,
- Configuration.buildUIServerSection(),
- );
- break;
+ Configuration.buildUIServerSection()
+ )
+ break
default:
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
- throw new Error(`Unknown configuration section '${sectionName}'`);
+ throw new Error(`Unknown configuration section '${sectionName}'`)
}
}
- private static buildUIServerSection(): UIServerConfiguration {
+ private static buildUIServerSection (): UIServerConfiguration {
let uiServerConfiguration: UIServerConfiguration = {
enabled: false,
type: ApplicationProtocol.WS,
options: {
host: Constants.DEFAULT_UI_SERVER_HOST,
- port: Constants.DEFAULT_UI_SERVER_PORT,
- },
- };
+ port: Constants.DEFAULT_UI_SERVER_PORT
+ }
+ }
if (hasOwnProp(Configuration.getConfigurationData(), ConfigurationSection.uiServer)) {
uiServerConfiguration = merge<UIServerConfiguration>(
uiServerConfiguration,
- Configuration.getConfigurationData()!.uiServer!,
- );
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ Configuration.getConfigurationData()!.uiServer!
+ )
}
- if (isCFEnvironment() === true) {
- delete uiServerConfiguration.options?.host;
- uiServerConfiguration.options!.port = parseInt(env.PORT!);
+ if (isCFEnvironment()) {
+ delete uiServerConfiguration.options?.host
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ uiServerConfiguration.options!.port = parseInt(env.PORT!)
}
- return uiServerConfiguration;
+ return uiServerConfiguration
}
- private static buildPerformanceStorageSection(): StorageConfiguration {
+ private static buildPerformanceStorageSection (): StorageConfiguration {
let storageConfiguration: StorageConfiguration = {
enabled: false,
type: StorageType.JSON_FILE,
- uri: getDefaultPerformanceStorageUri(StorageType.JSON_FILE),
- };
+ uri: getDefaultPerformanceStorageUri(StorageType.JSON_FILE)
+ }
if (hasOwnProp(Configuration.getConfigurationData(), ConfigurationSection.performanceStorage)) {
storageConfiguration = {
...storageConfiguration,
...Configuration.getConfigurationData()?.performanceStorage,
...(Configuration.getConfigurationData()?.performanceStorage?.type ===
StorageType.JSON_FILE &&
- Configuration.getConfigurationData()?.performanceStorage?.uri && {
- uri: buildPerformanceUriFilePath(
- new URL(Configuration.getConfigurationData()!.performanceStorage!.uri!).pathname,
- ),
- }),
- };
+ Configuration.getConfigurationData()?.performanceStorage?.uri != null && {
+ uri: buildPerformanceUriFilePath(
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ new URL(Configuration.getConfigurationData()!.performanceStorage!.uri!).pathname
+ )
+ })
+ }
}
- return storageConfiguration;
+ return storageConfiguration
}
- private static buildLogSection(): LogConfiguration {
+ private static buildLogSection (): LogConfiguration {
const defaultLogConfiguration: LogConfiguration = {
enabled: true,
file: 'logs/combined.log',
statisticsInterval: Constants.DEFAULT_LOG_STATISTICS_INTERVAL,
level: 'info',
format: 'simple',
- rotate: true,
- };
+ rotate: true
+ }
const deprecatedLogConfiguration: LogConfiguration = {
...(hasOwnProp(Configuration.getConfigurationData(), 'logEnabled') && {
- enabled: Configuration.getConfigurationData()?.logEnabled,
+ enabled: Configuration.getConfigurationData()?.logEnabled
}),
...(hasOwnProp(Configuration.getConfigurationData(), 'logFile') && {
- file: Configuration.getConfigurationData()?.logFile,
+ file: Configuration.getConfigurationData()?.logFile
}),
...(hasOwnProp(Configuration.getConfigurationData(), 'logErrorFile') && {
- errorFile: Configuration.getConfigurationData()?.logErrorFile,
+ errorFile: Configuration.getConfigurationData()?.logErrorFile
}),
...(hasOwnProp(Configuration.getConfigurationData(), 'logStatisticsInterval') && {
- statisticsInterval: Configuration.getConfigurationData()?.logStatisticsInterval,
+ statisticsInterval: Configuration.getConfigurationData()?.logStatisticsInterval
}),
...(hasOwnProp(Configuration.getConfigurationData(), 'logLevel') && {
- level: Configuration.getConfigurationData()?.logLevel,
+ level: Configuration.getConfigurationData()?.logLevel
}),
...(hasOwnProp(Configuration.getConfigurationData(), 'logConsole') && {
- console: Configuration.getConfigurationData()?.logConsole,
+ console: Configuration.getConfigurationData()?.logConsole
}),
...(hasOwnProp(Configuration.getConfigurationData(), 'logFormat') && {
- format: Configuration.getConfigurationData()?.logFormat,
+ format: Configuration.getConfigurationData()?.logFormat
}),
...(hasOwnProp(Configuration.getConfigurationData(), 'logRotate') && {
- rotate: Configuration.getConfigurationData()?.logRotate,
+ rotate: Configuration.getConfigurationData()?.logRotate
}),
...(hasOwnProp(Configuration.getConfigurationData(), 'logMaxFiles') && {
- maxFiles: Configuration.getConfigurationData()?.logMaxFiles,
+ maxFiles: Configuration.getConfigurationData()?.logMaxFiles
}),
...(hasOwnProp(Configuration.getConfigurationData(), 'logMaxSize') && {
- maxSize: Configuration.getConfigurationData()?.logMaxSize,
- }),
- };
+ maxSize: Configuration.getConfigurationData()?.logMaxSize
+ })
+ }
const logConfiguration: LogConfiguration = {
...defaultLogConfiguration,
...deprecatedLogConfiguration,
...(hasOwnProp(Configuration.getConfigurationData(), ConfigurationSection.log) &&
- Configuration.getConfigurationData()?.log),
- };
- return logConfiguration;
+ Configuration.getConfigurationData()?.log)
+ }
+ return logConfiguration
}
- private static buildWorkerSection(): WorkerConfiguration {
+ private static buildWorkerSection (): WorkerConfiguration {
const defaultWorkerConfiguration: WorkerConfiguration = {
processType: WorkerProcessType.workerSet,
startDelay: DEFAULT_WORKER_START_DELAY,
elementsPerWorker: 'auto',
elementStartDelay: DEFAULT_ELEMENT_START_DELAY,
poolMinSize: DEFAULT_POOL_MIN_SIZE,
- poolMaxSize: DEFAULT_POOL_MAX_SIZE,
- };
+ poolMaxSize: DEFAULT_POOL_MAX_SIZE
+ }
const deprecatedWorkerConfiguration: WorkerConfiguration = {
...(hasOwnProp(Configuration.getConfigurationData(), 'workerProcess') && {
- processType: Configuration.getConfigurationData()?.workerProcess,
+ processType: Configuration.getConfigurationData()?.workerProcess
}),
...(hasOwnProp(Configuration.getConfigurationData(), 'workerStartDelay') && {
- startDelay: Configuration.getConfigurationData()?.workerStartDelay,
+ startDelay: Configuration.getConfigurationData()?.workerStartDelay
}),
...(hasOwnProp(Configuration.getConfigurationData(), 'chargingStationsPerWorker') && {
- elementsPerWorker: Configuration.getConfigurationData()?.chargingStationsPerWorker,
+ elementsPerWorker: Configuration.getConfigurationData()?.chargingStationsPerWorker
}),
...(hasOwnProp(Configuration.getConfigurationData(), 'elementStartDelay') && {
- elementStartDelay: Configuration.getConfigurationData()?.elementStartDelay,
+ elementStartDelay: Configuration.getConfigurationData()?.elementStartDelay
}),
...(hasOwnProp(Configuration.getConfigurationData(), 'workerPoolMinSize') && {
- poolMinSize: Configuration.getConfigurationData()?.workerPoolMinSize,
+ poolMinSize: Configuration.getConfigurationData()?.workerPoolMinSize
}),
...(hasOwnProp(Configuration.getConfigurationData(), 'workerPoolMaxSize') && {
- poolMaxSize: Configuration.getConfigurationData()?.workerPoolMaxSize,
- }),
- };
+ poolMaxSize: Configuration.getConfigurationData()?.workerPoolMaxSize
+ })
+ }
hasOwnProp(Configuration.getConfigurationData(), 'workerPoolStrategy') &&
- delete Configuration.getConfigurationData()?.workerPoolStrategy;
+ delete Configuration.getConfigurationData()?.workerPoolStrategy
const workerConfiguration: WorkerConfiguration = {
...defaultWorkerConfiguration,
...deprecatedWorkerConfiguration,
...(hasOwnProp(Configuration.getConfigurationData(), ConfigurationSection.worker) &&
- Configuration.getConfigurationData()?.worker),
- };
- checkWorkerProcessType(workerConfiguration.processType!);
- checkWorkerElementsPerWorker(workerConfiguration.elementsPerWorker);
- return workerConfiguration;
+ Configuration.getConfigurationData()?.worker)
+ }
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ checkWorkerProcessType(workerConfiguration.processType!)
+ checkWorkerElementsPerWorker(workerConfiguration.elementsPerWorker)
+ return workerConfiguration
}
- private static checkDeprecatedConfigurationKeys() {
+ private static checkDeprecatedConfigurationKeys (): void {
// connection timeout
Configuration.warnDeprecatedConfigurationKey(
'autoReconnectTimeout',
undefined,
- "Use 'ConnectionTimeOut' OCPP parameter in charging station template instead",
- );
+ "Use 'ConnectionTimeOut' OCPP parameter in charging station template instead"
+ )
Configuration.warnDeprecatedConfigurationKey(
'connectionTimeout',
undefined,
- "Use 'ConnectionTimeOut' OCPP parameter in charging station template instead",
- );
+ "Use 'ConnectionTimeOut' OCPP parameter in charging station template instead"
+ )
// connection retries
Configuration.warnDeprecatedConfigurationKey(
'autoReconnectMaxRetries',
undefined,
- 'Use it in charging station template instead',
- );
+ 'Use it in charging station template instead'
+ )
// station template url(s)
Configuration.warnDeprecatedConfigurationKey(
'stationTemplateURLs',
undefined,
- "Use 'stationTemplateUrls' instead",
- );
+ "Use 'stationTemplateUrls' instead"
+ )
!isUndefined(
- Configuration.getConfigurationData()?.['stationTemplateURLs' as keyof ConfigurationData],
+ Configuration.getConfigurationData()?.['stationTemplateURLs' as keyof ConfigurationData]
) &&
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
(Configuration.getConfigurationData()!.stationTemplateUrls =
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
Configuration.getConfigurationData()![
'stationTemplateURLs' as keyof ConfigurationData
- ] as StationTemplateUrl[]);
+ ] as StationTemplateUrl[])
Configuration.getConfigurationData()?.stationTemplateUrls.forEach(
(stationTemplateUrl: StationTemplateUrl) => {
if (!isUndefined(stationTemplateUrl?.['numberOfStation' as keyof StationTemplateUrl])) {
console.error(
`${chalk.green(logPrefix())} ${chalk.red(
- `Deprecated configuration key 'numberOfStation' usage for template file '${stationTemplateUrl.file}' in 'stationTemplateUrls'. Use 'numberOfStations' instead`,
- )}`,
- );
+ `Deprecated configuration key 'numberOfStation' usage for template file '${stationTemplateUrl.file}' in 'stationTemplateUrls'. Use 'numberOfStations' instead`
+ )}`
+ )
}
- },
- );
+ }
+ )
// supervision url(s)
Configuration.warnDeprecatedConfigurationKey(
'supervisionURLs',
undefined,
- "Use 'supervisionUrls' instead",
- );
+ "Use 'supervisionUrls' instead"
+ )
// supervision urls distribution
Configuration.warnDeprecatedConfigurationKey(
'distributeStationToTenantEqually',
undefined,
- "Use 'supervisionUrlDistribution' instead",
- );
+ "Use 'supervisionUrlDistribution' instead"
+ )
Configuration.warnDeprecatedConfigurationKey(
'distributeStationsToTenantsEqually',
undefined,
- "Use 'supervisionUrlDistribution' instead",
- );
+ "Use 'supervisionUrlDistribution' instead"
+ )
// worker section
Configuration.warnDeprecatedConfigurationKey(
'useWorkerPool',
undefined,
- `Use '${ConfigurationSection.worker}' section to define the type of worker process model instead`,
- );
+ `Use '${ConfigurationSection.worker}' section to define the type of worker process model instead`
+ )
Configuration.warnDeprecatedConfigurationKey(
'workerProcess',
undefined,
- `Use '${ConfigurationSection.worker}' section to define the type of worker process model instead`,
- );
+ `Use '${ConfigurationSection.worker}' section to define the type of worker process model instead`
+ )
Configuration.warnDeprecatedConfigurationKey(
'workerStartDelay',
undefined,
- `Use '${ConfigurationSection.worker}' section to define the worker start delay instead`,
- );
+ `Use '${ConfigurationSection.worker}' section to define the worker start delay instead`
+ )
Configuration.warnDeprecatedConfigurationKey(
'chargingStationsPerWorker',
undefined,
- `Use '${ConfigurationSection.worker}' section to define the number of element(s) per worker instead`,
- );
+ `Use '${ConfigurationSection.worker}' section to define the number of element(s) per worker instead`
+ )
Configuration.warnDeprecatedConfigurationKey(
'elementStartDelay',
undefined,
- `Use '${ConfigurationSection.worker}' section to define the worker's element start delay instead`,
- );
+ `Use '${ConfigurationSection.worker}' section to define the worker's element start delay instead`
+ )
Configuration.warnDeprecatedConfigurationKey(
'workerPoolMinSize',
undefined,
- `Use '${ConfigurationSection.worker}' section to define the worker pool minimum size instead`,
- );
+ `Use '${ConfigurationSection.worker}' section to define the worker pool minimum size instead`
+ )
Configuration.warnDeprecatedConfigurationKey(
'workerPoolSize',
undefined,
- `Use '${ConfigurationSection.worker}' section to define the worker pool maximum size instead`,
- );
+ `Use '${ConfigurationSection.worker}' section to define the worker pool maximum size instead`
+ )
Configuration.warnDeprecatedConfigurationKey(
'workerPoolMaxSize',
undefined,
- `Use '${ConfigurationSection.worker}' section to define the worker pool maximum size instead`,
- );
+ `Use '${ConfigurationSection.worker}' section to define the worker pool maximum size instead`
+ )
Configuration.warnDeprecatedConfigurationKey(
'workerPoolStrategy',
undefined,
- `Use '${ConfigurationSection.worker}' section to define the worker pool strategy instead`,
- );
+ `Use '${ConfigurationSection.worker}' section to define the worker pool strategy instead`
+ )
Configuration.warnDeprecatedConfigurationKey(
'poolStrategy',
ConfigurationSection.worker,
- 'Not publicly exposed to end users',
- );
+ 'Not publicly exposed to end users'
+ )
if (
Configuration.getConfigurationData()?.worker?.processType ===
('staticPool' as WorkerProcessType)
) {
console.error(
`${chalk.green(logPrefix())} ${chalk.red(
- `Deprecated configuration 'staticPool' value usage in worker section 'processType' field. Use '${WorkerProcessType.fixedPool}' value instead`,
- )}`,
- );
+ `Deprecated configuration 'staticPool' value usage in worker section 'processType' field. Use '${WorkerProcessType.fixedPool}' value instead`
+ )}`
+ )
}
// log section
Configuration.warnDeprecatedConfigurationKey(
'logEnabled',
undefined,
- `Use '${ConfigurationSection.log}' section to define the logging enablement instead`,
- );
+ `Use '${ConfigurationSection.log}' section to define the logging enablement instead`
+ )
Configuration.warnDeprecatedConfigurationKey(
'logFile',
undefined,
- `Use '${ConfigurationSection.log}' section to define the log file instead`,
- );
+ `Use '${ConfigurationSection.log}' section to define the log file instead`
+ )
Configuration.warnDeprecatedConfigurationKey(
'logErrorFile',
undefined,
- `Use '${ConfigurationSection.log}' section to define the log error file instead`,
- );
+ `Use '${ConfigurationSection.log}' section to define the log error file instead`
+ )
Configuration.warnDeprecatedConfigurationKey(
'logConsole',
undefined,
- `Use '${ConfigurationSection.log}' section to define the console logging enablement instead`,
- );
+ `Use '${ConfigurationSection.log}' section to define the console logging enablement instead`
+ )
Configuration.warnDeprecatedConfigurationKey(
'logStatisticsInterval',
undefined,
- `Use '${ConfigurationSection.log}' section to define the log statistics interval instead`,
- );
+ `Use '${ConfigurationSection.log}' section to define the log statistics interval instead`
+ )
Configuration.warnDeprecatedConfigurationKey(
'logLevel',
undefined,
- `Use '${ConfigurationSection.log}' section to define the log level instead`,
- );
+ `Use '${ConfigurationSection.log}' section to define the log level instead`
+ )
Configuration.warnDeprecatedConfigurationKey(
'logFormat',
undefined,
- `Use '${ConfigurationSection.log}' section to define the log format instead`,
- );
+ `Use '${ConfigurationSection.log}' section to define the log format instead`
+ )
Configuration.warnDeprecatedConfigurationKey(
'logRotate',
undefined,
- `Use '${ConfigurationSection.log}' section to define the log rotation enablement instead`,
- );
+ `Use '${ConfigurationSection.log}' section to define the log rotation enablement instead`
+ )
Configuration.warnDeprecatedConfigurationKey(
'logMaxFiles',
undefined,
- `Use '${ConfigurationSection.log}' section to define the log maximum files instead`,
- );
+ `Use '${ConfigurationSection.log}' section to define the log maximum files instead`
+ )
Configuration.warnDeprecatedConfigurationKey(
'logMaxSize',
undefined,
- `Use '${ConfigurationSection.log}' section to define the log maximum size instead`,
- );
+ `Use '${ConfigurationSection.log}' section to define the log maximum size instead`
+ )
// performanceStorage section
Configuration.warnDeprecatedConfigurationKey(
'URI',
ConfigurationSection.performanceStorage,
- "Use 'uri' instead",
- );
+ "Use 'uri' instead"
+ )
// uiServer section
if (hasOwnProp(Configuration.getConfigurationData(), 'uiWebSocketServer')) {
console.error(
`${chalk.green(logPrefix())} ${chalk.red(
- `Deprecated configuration section 'uiWebSocketServer' usage. Use '${ConfigurationSection.uiServer}' instead`,
- )}`,
- );
+ `Deprecated configuration section 'uiWebSocketServer' usage. Use '${ConfigurationSection.uiServer}' instead`
+ )}`
+ )
}
}
- private static warnDeprecatedConfigurationKey(
+ private static warnDeprecatedConfigurationKey (
key: string,
sectionName?: string,
- logMsgToAppend = '',
- ) {
+ logMsgToAppend = ''
+ ): void {
if (
- sectionName &&
+ sectionName != null &&
!isUndefined(
- Configuration.getConfigurationData()?.[sectionName as keyof ConfigurationData],
+ Configuration.getConfigurationData()?.[sectionName as keyof ConfigurationData]
) &&
!isUndefined(
(
Configuration.getConfigurationData()?.[sectionName as keyof ConfigurationData] as Record<
- string,
- unknown
+ string,
+ unknown
>
- )?.[key],
+ )?.[key]
)
) {
console.error(
`${chalk.green(logPrefix())} ${chalk.red(
`Deprecated configuration key '${key}' usage in section '${sectionName}'${
logMsgToAppend.trim().length > 0 ? `. ${logMsgToAppend}` : ''
- }`,
- )}`,
- );
+ }`
+ )}`
+ )
} else if (
!isUndefined(Configuration.getConfigurationData()?.[key as keyof ConfigurationData])
) {
`${chalk.green(logPrefix())} ${chalk.red(
`Deprecated configuration key '${key}' usage${
logMsgToAppend.trim().length > 0 ? `. ${logMsgToAppend}` : ''
- }`,
- )}`,
- );
+ }`
+ )}`
+ )
}
}
- private static getConfigurationData(): ConfigurationData | undefined {
- if (!Configuration.configurationData) {
+ private static getConfigurationData (): ConfigurationData | undefined {
+ if (Configuration.configurationData == null) {
try {
Configuration.configurationData = JSON.parse(
- readFileSync(Configuration.configurationFile, 'utf8'),
- ) as ConfigurationData;
- if (!Configuration.configurationFileWatcher) {
- Configuration.configurationFileWatcher = Configuration.getConfigurationFileWatcher();
+ readFileSync(Configuration.configurationFile, 'utf8')
+ ) as ConfigurationData
+ if (Configuration.configurationFileWatcher == null) {
+ Configuration.configurationFileWatcher = Configuration.getConfigurationFileWatcher()
}
} catch (error) {
handleFileException(
Configuration.configurationFile,
FileType.Configuration,
error as NodeJS.ErrnoException,
- logPrefix(),
- );
+ logPrefix()
+ )
}
}
- return Configuration.configurationData;
+ return Configuration.configurationData
}
- private static getConfigurationFileWatcher(): FSWatcher | undefined {
+ private static getConfigurationFileWatcher (): FSWatcher | undefined {
try {
return watch(Configuration.configurationFile, (event, filename): void => {
if (
!Configuration.configurationFileReloading &&
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
filename!.trim()!.length > 0 &&
event === 'change'
) {
- Configuration.configurationFileReloading = true;
- const consoleWarnOnce = once(console.warn, this);
+ Configuration.configurationFileReloading = true
+ const consoleWarnOnce = once(console.warn, this)
consoleWarnOnce(
`${chalk.green(logPrefix())} ${chalk.yellow(
- `${FileType.Configuration} ${this.configurationFile} file have changed, reload`,
- )}`,
- );
- delete Configuration.configurationData;
- Configuration.configurationSectionCache.clear();
+ `${FileType.Configuration} ${this.configurationFile} file have changed, reload`
+ )}`
+ )
+ delete Configuration.configurationData
+ Configuration.configurationSectionCache.clear()
if (!isUndefined(Configuration.configurationChangeCallback)) {
Configuration.configurationChangeCallback()
.catch((error) => {
- throw typeof error === 'string' ? new Error(error) : error;
+ throw typeof error === 'string' ? new Error(error) : error
})
.finally(() => {
- Configuration.configurationFileReloading = false;
- });
+ Configuration.configurationFileReloading = false
+ })
} else {
- Configuration.configurationFileReloading = false;
+ Configuration.configurationFileReloading = false
}
}
- });
+ })
} catch (error) {
handleFileException(
Configuration.configurationFile,
FileType.Configuration,
error as NodeJS.ErrnoException,
- logPrefix(),
- );
+ logPrefix()
+ )
}
}
}
-import { dirname, join, resolve } from 'node:path';
-import { fileURLToPath } from 'node:url';
+import { dirname, join, resolve } from 'node:path'
+import { fileURLToPath } from 'node:url'
-import chalk from 'chalk';
+import chalk from 'chalk'
-import { Constants } from './Constants.js';
-import { isNotEmptyString, logPrefix as utilsLogPrefix } from './Utils.js';
-import { type ElementsPerWorkerType, FileType, StorageType } from '../types/index.js';
-import { WorkerProcessType } from '../worker/index.js';
+import { Constants } from './Constants.js'
+import { isNotEmptyString, logPrefix as utilsLogPrefix } from './Utils.js'
+import { type ElementsPerWorkerType, type FileType, StorageType } from '../types/index.js'
+import { WorkerProcessType } from '../worker/index.js'
export const logPrefix = (): string => {
- return utilsLogPrefix(' Simulator configuration |');
-};
+ return utilsLogPrefix(' Simulator configuration |')
+}
-export const buildPerformanceUriFilePath = (file: string) => {
- return `file://${join(resolve(dirname(fileURLToPath(import.meta.url)), '../'), file)}`;
-};
+export const buildPerformanceUriFilePath = (file: string): string => {
+ return `file://${join(resolve(dirname(fileURLToPath(import.meta.url)), '../'), file)}`
+}
-export const getDefaultPerformanceStorageUri = (storageType: StorageType) => {
+export const getDefaultPerformanceStorageUri = (storageType: StorageType): string => {
switch (storageType) {
case StorageType.JSON_FILE:
return buildPerformanceUriFilePath(
- `${Constants.DEFAULT_PERFORMANCE_DIRECTORY}/${Constants.DEFAULT_PERFORMANCE_RECORDS_FILENAME}`,
- );
+ `${Constants.DEFAULT_PERFORMANCE_DIRECTORY}/${Constants.DEFAULT_PERFORMANCE_RECORDS_FILENAME}`
+ )
case StorageType.SQLITE:
return buildPerformanceUriFilePath(
- `${Constants.DEFAULT_PERFORMANCE_DIRECTORY}/${Constants.DEFAULT_PERFORMANCE_RECORDS_DB_NAME}.db`,
- );
+ `${Constants.DEFAULT_PERFORMANCE_DIRECTORY}/${Constants.DEFAULT_PERFORMANCE_RECORDS_DB_NAME}.db`
+ )
default:
- throw new Error(`Unsupported storage type '${storageType}'`);
+ throw new Error(`Unsupported storage type '${storageType}'`)
}
-};
+}
export const handleFileException = (
file: string,
fileType: FileType,
error: NodeJS.ErrnoException,
- logPfx: string,
+ logPfx: string
): void => {
- const prefix = isNotEmptyString(logPfx) ? `${logPfx} ` : '';
- let logMsg: string;
+ const prefix = isNotEmptyString(logPfx) ? `${logPfx} ` : ''
+ let logMsg: string
switch (error.code) {
case 'ENOENT':
- logMsg = `${fileType} file ${file} not found: `;
- break;
+ logMsg = `${fileType} file ${file} not found: `
+ break
case 'EEXIST':
- logMsg = `${fileType} file ${file} already exists: `;
- break;
+ logMsg = `${fileType} file ${file} already exists: `
+ break
case 'EACCES':
- logMsg = `${fileType} file ${file} access denied: `;
- break;
+ logMsg = `${fileType} file ${file} access denied: `
+ break
case 'EPERM':
- logMsg = `${fileType} file ${file} permission denied: `;
- break;
+ logMsg = `${fileType} file ${file} permission denied: `
+ break
default:
- logMsg = `${fileType} file ${file} error: `;
+ logMsg = `${fileType} file ${file} error: `
}
- console.error(`${chalk.green(prefix)}${chalk.red(logMsg)}`, error);
- throw error;
-};
+ console.error(`${chalk.green(prefix)}${chalk.red(logMsg)}`, error)
+ throw error
+}
export const checkWorkerProcessType = (workerProcessType: WorkerProcessType): void => {
if (!Object.values(WorkerProcessType).includes(workerProcessType)) {
throw new SyntaxError(
- `Invalid worker process type '${workerProcessType}' defined in configuration`,
- );
+ `Invalid worker process type '${workerProcessType}' defined in configuration`
+ )
}
-};
+}
export const checkWorkerElementsPerWorker = (
- elementsPerWorker: ElementsPerWorkerType | undefined,
+ elementsPerWorker: ElementsPerWorkerType | undefined
): void => {
if (
elementsPerWorker !== undefined &&
!Number.isSafeInteger(elementsPerWorker)
) {
throw new SyntaxError(
- `Invalid number of elements per worker '${elementsPerWorker}' defined in configuration`,
- );
+ `Invalid number of elements per worker '${elementsPerWorker}' defined in configuration`
+ )
}
if (Number.isSafeInteger(elementsPerWorker) && (elementsPerWorker as number) <= 0) {
throw RangeError(
- `Invalid negative or zero number of elements per worker '${elementsPerWorker}' defined in configuration`,
- );
+ `Invalid negative or zero number of elements per worker '${elementsPerWorker}' defined in configuration`
+ )
}
-};
+}
type ChargingStationInfo,
CurrentType,
OCPPVersion,
- VendorParametersKey,
-} from '../types/index.js';
+ VendorParametersKey
+} from '../types/index.js'
+// eslint-disable-next-line @typescript-eslint/no-extraneous-class
export class Constants {
static readonly DEFAULT_STATION_INFO: Partial<ChargingStationInfo> = Object.freeze({
enableStatistics: false,
autoReconnectMaxRetries: -1,
registrationMaxRetries: -1,
reconnectExponentialDelay: false,
- stopTransactionsOnStopped: true,
- });
+ stopTransactionsOnStopped: true
+ })
- static readonly DEFAULT_BOOT_NOTIFICATION_INTERVAL = 60000; // Ms
- static readonly DEFAULT_HEARTBEAT_INTERVAL = 60000; // Ms
- static readonly DEFAULT_METER_VALUES_INTERVAL = 60000; // Ms
+ static readonly DEFAULT_BOOT_NOTIFICATION_INTERVAL = 60000 // Ms
+ static readonly DEFAULT_HEARTBEAT_INTERVAL = 60000 // Ms
+ static readonly DEFAULT_METER_VALUES_INTERVAL = 60000 // Ms
- static readonly CHARGING_STATION_DEFAULT_RESET_TIME = 60000; // Ms
- static readonly CHARGING_STATION_ATG_AVAILABILITY_TIME = 1000; // Ms
- static readonly CHARGING_STATION_ATG_INITIALIZATION_TIME = 1000; // Ms
+ static readonly CHARGING_STATION_DEFAULT_RESET_TIME = 60000 // Ms
+ static readonly CHARGING_STATION_ATG_AVAILABILITY_TIME = 1000 // Ms
+ static readonly CHARGING_STATION_ATG_INITIALIZATION_TIME = 1000 // Ms
static readonly DEFAULT_ATG_CONFIGURATION: AutomaticTransactionGeneratorConfiguration =
Object.freeze({
maxDelayBetweenTwoTransactions: 30,
probabilityOfStart: 1,
stopAfterHours: 0.25,
- stopOnConnectionFailure: true,
- });
+ stopOnConnectionFailure: true
+ })
// See https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string
static readonly SEMVER_PATTERN =
- '^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$';
+ '^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$'
- static readonly DEFAULT_CIRCULAR_BUFFER_CAPACITY = 4096;
+ static readonly DEFAULT_CIRCULAR_BUFFER_CAPACITY = 4096
- static readonly DEFAULT_HASH_ALGORITHM = 'sha384';
+ static readonly DEFAULT_HASH_ALGORITHM = 'sha384'
- static readonly DEFAULT_IDTAG = '00000000';
+ static readonly DEFAULT_IDTAG = '00000000'
- static readonly DEFAULT_CONNECTION_TIMEOUT = 30;
+ static readonly DEFAULT_CONNECTION_TIMEOUT = 30
- static readonly DEFAULT_LOG_STATISTICS_INTERVAL = 60; // Seconds
+ static readonly DEFAULT_LOG_STATISTICS_INTERVAL = 60 // Seconds
- static readonly DEFAULT_FLUCTUATION_PERCENT = 5;
+ static readonly DEFAULT_FLUCTUATION_PERCENT = 5
- static readonly DEFAULT_PERFORMANCE_DIRECTORY = 'performance';
- static readonly DEFAULT_PERFORMANCE_RECORDS_FILENAME = 'performanceRecords.json';
- static readonly DEFAULT_PERFORMANCE_RECORDS_DB_NAME = 'e-mobility-charging-stations-simulator';
- static readonly PERFORMANCE_RECORDS_TABLE = 'performance_records';
+ static readonly DEFAULT_PERFORMANCE_DIRECTORY = 'performance'
+ static readonly DEFAULT_PERFORMANCE_RECORDS_FILENAME = 'performanceRecords.json'
+ static readonly DEFAULT_PERFORMANCE_RECORDS_DB_NAME = 'e-mobility-charging-stations-simulator'
+ static readonly PERFORMANCE_RECORDS_TABLE = 'performance_records'
- static readonly DEFAULT_UI_SERVER_HOST = 'localhost';
- static readonly DEFAULT_UI_SERVER_PORT = 8080;
+ static readonly DEFAULT_UI_SERVER_HOST = 'localhost'
+ static readonly DEFAULT_UI_SERVER_PORT = 8080
- static readonly UNKNOWN_COMMAND = 'unknown command';
+ static readonly UNKNOWN_COMMAND = 'unknown command'
- static readonly MAX_RANDOM_INTEGER = 281474976710654;
+ static readonly MAX_RANDOM_INTEGER = 281474976710654
- static readonly STOP_CHARGING_STATIONS_TIMEOUT = 120000; // Ms
+ static readonly STOP_CHARGING_STATIONS_TIMEOUT = 120000 // Ms
- static readonly EMPTY_FROZEN_OBJECT = Object.freeze({});
+ static readonly EMPTY_FROZEN_OBJECT = Object.freeze({})
static readonly EMPTY_FUNCTION = Object.freeze(() => {
/* This is intentional */
- });
+ })
- static readonly DEFAULT_MESSAGE_BUFFER_FLUSH_INTERVAL = 60000; // Ms
+ static readonly DEFAULT_MESSAGE_BUFFER_FLUSH_INTERVAL = 60000 // Ms
- private constructor() {
+ private constructor () {
// This is intentional
}
}
/**
* Targeted to AC related values calculation.
*/
+// eslint-disable-next-line @typescript-eslint/no-extraneous-class
export class ACElectricUtils {
- private constructor() {
+ private constructor () {
// This is intentional
}
- static powerTotal(nbOfPhases: number, V: number, Iph: number, cosPhi = 1): number {
- return nbOfPhases * ACElectricUtils.powerPerPhase(V, Iph, cosPhi);
+ static powerTotal (nbOfPhases: number, V: number, Iph: number, cosPhi = 1): number {
+ return nbOfPhases * ACElectricUtils.powerPerPhase(V, Iph, cosPhi)
}
- static powerPerPhase(V: number, Iph: number, cosPhi = 1): number {
- const powerPerPhase = V * Iph * cosPhi;
+ static powerPerPhase (V: number, Iph: number, cosPhi = 1): number {
+ const powerPerPhase = V * Iph * cosPhi
if (cosPhi === 1) {
- return powerPerPhase;
+ return powerPerPhase
}
- return Math.round(powerPerPhase);
+ return Math.round(powerPerPhase)
}
- static amperageTotal(nbOfPhases: number, Iph: number): number {
- return nbOfPhases * Iph;
+ static amperageTotal (nbOfPhases: number, Iph: number): number {
+ return nbOfPhases * Iph
}
- static amperageTotalFromPower(P: number, V: number, cosPhi = 1): number {
- const amperage = P / (V * cosPhi);
+ static amperageTotalFromPower (P: number, V: number, cosPhi = 1): number {
+ const amperage = P / (V * cosPhi)
if (cosPhi === 1 && P % V === 0) {
- return amperage;
+ return amperage
}
- return Math.round(amperage);
+ return Math.round(amperage)
}
- static amperagePerPhaseFromPower(nbOfPhases: number, P: number, V: number, cosPhi = 1): number {
- const amperage = ACElectricUtils.amperageTotalFromPower(P, V, cosPhi);
- const amperagePerPhase = amperage / nbOfPhases;
+ static amperagePerPhaseFromPower (nbOfPhases: number, P: number, V: number, cosPhi = 1): number {
+ const amperage = ACElectricUtils.amperageTotalFromPower(P, V, cosPhi)
+ const amperagePerPhase = amperage / nbOfPhases
if (amperage % nbOfPhases === 0) {
- return amperagePerPhase;
+ return amperagePerPhase
}
- return Math.round(amperagePerPhase);
+ return Math.round(amperagePerPhase)
}
}
/**
* Targeted to DC related values calculation.
*/
+// eslint-disable-next-line @typescript-eslint/no-extraneous-class
export class DCElectricUtils {
- private constructor() {
+ private constructor () {
// This is intentional
}
- static power(V: number, I: number): number {
- return V * I;
+ static power (V: number, I: number): number {
+ return V * I
}
- static amperage(P: number, V: number): number {
- const amperage = P / V;
+ static amperage (P: number, V: number): number {
+ const amperage = P / V
if (P % V === 0) {
- return amperage;
+ return amperage
}
- return Math.round(amperage);
+ return Math.round(amperage)
}
}
-import process from 'node:process';
+import process from 'node:process'
-import chalk from 'chalk';
+import chalk from 'chalk'
-import { logger } from './Logger.js';
-import { isNotEmptyString } from './Utils.js';
-import type { ChargingStation } from '../charging-station/index.js';
+import { logger } from './Logger.js'
+import { isNotEmptyString } from './Utils.js'
+import type { ChargingStation } from '../charging-station/index.js'
import type {
EmptyObject,
FileType,
HandleErrorParams,
IncomingRequestCommand,
JsonType,
- RequestCommand,
-} from '../types/index.js';
+ RequestCommand
+} from '../types/index.js'
const defaultErrorParams = {
throwError: true,
- consoleOut: false,
-};
+ consoleOut: false
+}
export const handleUncaughtException = (): void => {
process.on('uncaughtException', (error: Error) => {
- console.error(chalk.red('Uncaught exception: '), error);
- });
-};
+ console.error(chalk.red('Uncaught exception: '), error)
+ })
+}
export const handleUnhandledRejection = (): void => {
process.on('unhandledRejection', (reason: unknown) => {
- console.error(chalk.red('Unhandled rejection: '), reason);
- });
-};
+ console.error(chalk.red('Unhandled rejection: '), reason)
+ })
+}
export const handleFileException = (
file: string,
fileType: FileType,
error: NodeJS.ErrnoException,
logPrefix: string,
- params: HandleErrorParams<EmptyObject> = defaultErrorParams,
+ params: HandleErrorParams<EmptyObject> = defaultErrorParams
): void => {
- setDefaultErrorParams(params);
- const prefix = isNotEmptyString(logPrefix) ? `${logPrefix} ` : '';
- let logMsg: string;
+ setDefaultErrorParams(params)
+ const prefix = isNotEmptyString(logPrefix) ? `${logPrefix} ` : ''
+ let logMsg: string
switch (error.code) {
case 'ENOENT':
- logMsg = `${fileType} file ${file} not found:`;
- break;
+ logMsg = `${fileType} file ${file} not found:`
+ break
case 'EEXIST':
- logMsg = `${fileType} file ${file} already exists:`;
- break;
+ logMsg = `${fileType} file ${file} already exists:`
+ break
case 'EACCES':
- logMsg = `${fileType} file ${file} access denied:`;
- break;
+ logMsg = `${fileType} file ${file} access denied:`
+ break
case 'EPERM':
- logMsg = `${fileType} file ${file} permission denied:`;
- break;
+ logMsg = `${fileType} file ${file} permission denied:`
+ break
default:
- logMsg = `${fileType} file ${file} error:`;
+ logMsg = `${fileType} file ${file} error:`
}
if (params?.consoleOut === true) {
- logMsg = `${logMsg} `;
- if (params?.throwError) {
- console.error(`${chalk.green(prefix)}${chalk.red(logMsg)}`, error);
+ logMsg = `${logMsg} `
+ if (params?.throwError === true) {
+ console.error(`${chalk.green(prefix)}${chalk.red(logMsg)}`, error)
} else {
- console.warn(`${chalk.green(prefix)}${chalk.yellow(logMsg)}`, error);
+ console.warn(`${chalk.green(prefix)}${chalk.yellow(logMsg)}`, error)
}
} else if (params?.consoleOut === false) {
- if (params?.throwError) {
- logger.error(`${prefix}${logMsg}`, error);
+ if (params?.throwError === true) {
+ logger.error(`${prefix}${logMsg}`, error)
} else {
- logger.warn(`${prefix}${logMsg}`, error);
+ logger.warn(`${prefix}${logMsg}`, error)
}
}
- if (params?.throwError) {
- throw error;
+ if (params?.throwError === true) {
+ throw error
}
-};
+}
export const handleSendMessageError = (
chargingStation: ChargingStation,
commandName: RequestCommand | IncomingRequestCommand,
error: Error,
- params: HandleErrorParams<EmptyObject> = { throwError: false, consoleOut: false },
+ params: HandleErrorParams<EmptyObject> = { throwError: false, consoleOut: false }
): void => {
- setDefaultErrorParams(params, { throwError: false, consoleOut: false });
- logger.error(`${chargingStation.logPrefix()} Request command '${commandName}' error:`, error);
+ setDefaultErrorParams(params, { throwError: false, consoleOut: false })
+ logger.error(`${chargingStation.logPrefix()} Request command '${commandName}' error:`, error)
if (params?.throwError === true) {
- throw error;
+ throw error
}
-};
+}
export const setDefaultErrorParams = <T extends JsonType>(
params: HandleErrorParams<T>,
- defaultParams: HandleErrorParams<T> = defaultErrorParams,
+ defaultParams: HandleErrorParams<T> = defaultErrorParams
): HandleErrorParams<T> => {
- params = { ...defaultParams, ...params };
- return params;
-};
+ params = { ...defaultParams, ...params }
+ return params
+}
-import { type FSWatcher, type WatchListener, readFileSync, watch } from 'node:fs';
+import { type FSWatcher, type WatchListener, readFileSync, watch } from 'node:fs'
-import { handleFileException } from './ErrorUtils.js';
-import { logger } from './Logger.js';
-import { isNotEmptyString } from './Utils.js';
-import type { FileType, JsonType } from '../types/index.js';
+import { handleFileException } from './ErrorUtils.js'
+import { logger } from './Logger.js'
+import { isNotEmptyString } from './Utils.js'
+import type { FileType, JsonType } from '../types/index.js'
export const watchJsonFile = <T extends JsonType>(
file: string,
listener: WatchListener<string> = (event, filename) => {
if (isNotEmptyString(filename) && event === 'change') {
try {
- logger.debug(`${logPrefix} ${fileType} file ${file} have changed, reload`);
- refreshedVariable && (refreshedVariable = JSON.parse(readFileSync(file, 'utf8')) as T);
+ logger.debug(`${logPrefix} ${fileType} file ${file} have changed, reload`)
+ refreshedVariable != null &&
+ (refreshedVariable = JSON.parse(readFileSync(file, 'utf8')) as T)
} catch (error) {
handleFileException(file, fileType, error as NodeJS.ErrnoException, logPrefix, {
- throwError: false,
- });
+ throwError: false
+ })
}
}
- },
+ }
): FSWatcher | undefined => {
if (isNotEmptyString(file)) {
try {
- return watch(file, listener);
+ return watch(file, listener)
} catch (error) {
handleFileException(file, fileType, error as NodeJS.ErrnoException, logPrefix, {
- throwError: false,
- });
+ throwError: false
+ })
}
} else {
- logger.info(`${logPrefix} No ${fileType} file to watch given. Not monitoring its changes`);
+ logger.info(`${logPrefix} No ${fileType} file to watch given. Not monitoring its changes`)
}
-};
+}
-import type { FormatWrap } from 'logform';
-import { createLogger, format, type transport } from 'winston';
-import TransportType from 'winston/lib/winston/transports/index.js';
-import DailyRotateFile from 'winston-daily-rotate-file';
+import type { FormatWrap } from 'logform'
+import { createLogger, format, type transport } from 'winston'
+import TransportType from 'winston/lib/winston/transports/index.js'
+import DailyRotateFile from 'winston-daily-rotate-file'
-import { Configuration } from './Configuration.js';
-import { insertAt } from './Utils.js';
-import { ConfigurationSection, type LogConfiguration } from '../types/index.js';
+import { Configuration } from './Configuration.js'
+import { insertAt } from './Utils.js'
+import { ConfigurationSection, type LogConfiguration } from '../types/index.js'
const logConfiguration = Configuration.getConfigurationSection<LogConfiguration>(
- ConfigurationSection.log,
-);
-let transports: transport[];
+ ConfigurationSection.log
+)
+let transports: transport[]
if (logConfiguration.rotate === true) {
- const logMaxFiles = logConfiguration.maxFiles;
- const logMaxSize = logConfiguration.maxSize;
+ const logMaxFiles = logConfiguration.maxFiles
+ const logMaxSize = logConfiguration.maxSize
transports = [
new DailyRotateFile({
filename: insertAt(
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
logConfiguration.errorFile!,
'-%DATE%',
- logConfiguration.errorFile!.indexOf('.log'),
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ logConfiguration.errorFile!.indexOf('.log')
),
level: 'error',
- ...(logMaxFiles && { maxFiles: logMaxFiles }),
- ...(logMaxSize && { maxSize: logMaxSize }),
+ ...(logMaxFiles != null && { maxFiles: logMaxFiles }),
+ ...(logMaxSize != null && { maxSize: logMaxSize })
}),
new DailyRotateFile({
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
filename: insertAt(logConfiguration.file!, '-%DATE%', logConfiguration.file!.indexOf('.log')),
- ...(logMaxFiles && { maxFiles: logMaxFiles }),
- ...(logMaxSize && { maxSize: logMaxSize }),
- }),
- ];
+ ...(logMaxFiles != null && { maxFiles: logMaxFiles }),
+ ...(logMaxSize != null && { maxSize: logMaxSize })
+ })
+ ]
} else {
transports = [
new TransportType.File({
filename: logConfiguration.errorFile,
- level: 'error',
+ level: 'error'
}),
new TransportType.File({
- filename: logConfiguration.file,
- }),
- ];
+ filename: logConfiguration.file
+ })
+ ]
}
export const logger = createLogger({
- silent: !logConfiguration.enabled,
+ silent: logConfiguration.enabled === false,
level: logConfiguration.level,
format: format.combine(
format.splat(),
- (format[logConfiguration.format! as keyof FormatWrap] as FormatWrap)(),
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ (format[logConfiguration.format! as keyof FormatWrap] as FormatWrap)()
),
- transports,
-});
+ transports
+})
//
// If enabled, log to the `console` with the format:
// `${info.level}: ${info.message} JSON.stringify({ ...rest }) `
//
-if (logConfiguration.console) {
+if (logConfiguration.console === true) {
logger.add(
new TransportType.Console({
format: format.combine(
format.splat(),
- (format[logConfiguration.format! as keyof FormatWrap] as FormatWrap)(),
- ),
- }),
- );
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ (format[logConfiguration.format! as keyof FormatWrap] as FormatWrap)()
+ )
+ })
+ )
}
OutputFormat,
buildChargingStationAutomaticTransactionGeneratorConfiguration,
buildConnectorsStatus,
- buildEvsesStatus,
-} from './ChargingStationConfigurationUtils.js';
-import type { ChargingStation } from '../charging-station/index.js';
+ buildEvsesStatus
+} from './ChargingStationConfigurationUtils.js'
+import type { ChargingStation } from '../charging-station/index.js'
import {
type ChargingStationData,
type ChargingStationWorkerMessage,
ChargingStationWorkerMessageEvents,
- type Statistics,
-} from '../types/index.js';
+ type Statistics
+} from '../types/index.js'
export const buildStartedMessage = (
- chargingStation: ChargingStation,
+ chargingStation: ChargingStation
): ChargingStationWorkerMessage<ChargingStationData> => {
return {
event: ChargingStationWorkerMessageEvents.started,
- data: buildChargingStationDataPayload(chargingStation),
- };
-};
+ data: buildChargingStationDataPayload(chargingStation)
+ }
+}
export const buildStoppedMessage = (
- chargingStation: ChargingStation,
+ chargingStation: ChargingStation
): ChargingStationWorkerMessage<ChargingStationData> => {
return {
event: ChargingStationWorkerMessageEvents.stopped,
- data: buildChargingStationDataPayload(chargingStation),
- };
-};
+ data: buildChargingStationDataPayload(chargingStation)
+ }
+}
export const buildUpdatedMessage = (
- chargingStation: ChargingStation,
+ chargingStation: ChargingStation
): ChargingStationWorkerMessage<ChargingStationData> => {
return {
event: ChargingStationWorkerMessageEvents.updated,
- data: buildChargingStationDataPayload(chargingStation),
- };
-};
+ data: buildChargingStationDataPayload(chargingStation)
+ }
+}
export const buildPerformanceStatisticsMessage = (
- statistics: Statistics,
+ statistics: Statistics
): ChargingStationWorkerMessage<Statistics> => {
return {
event: ChargingStationWorkerMessageEvents.performanceStatistics,
- data: statistics,
- };
-};
+ data: statistics
+ }
+}
const buildChargingStationDataPayload = (chargingStation: ChargingStation): ChargingStationData => {
return {
stationInfo: chargingStation.stationInfo,
connectors: buildConnectorsStatus(chargingStation),
evses: buildEvsesStatus(chargingStation, OutputFormat.worker),
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
ocppConfiguration: chargingStation.ocppConfiguration!,
wsState: chargingStation?.wsConnection?.readyState,
bootNotificationResponse: chargingStation.bootNotificationResponse,
- ...(chargingStation.automaticTransactionGenerator && {
+ ...(chargingStation.automaticTransactionGenerator != null && {
automaticTransactionGenerator:
- buildChargingStationAutomaticTransactionGeneratorConfiguration(chargingStation),
- }),
- };
-};
+ buildChargingStationAutomaticTransactionGeneratorConfiguration(chargingStation)
+ })
+ }
+}
-import { isEmptyArray, isNullOrUndefined } from './Utils.js';
+import { isEmptyArray, isNullOrUndefined } from './Utils.js'
/**
* Computes the average of the given data set.
*/
export const average = (dataSet: number[]): number => {
if (Array.isArray(dataSet) && dataSet.length === 0) {
- return 0;
+ return 0
}
if (Array.isArray(dataSet) && dataSet.length === 1) {
- return dataSet[0];
+ return dataSet[0]
}
- return dataSet.reduce((accumulator, nb) => accumulator + nb, 0) / dataSet.length;
-};
+ return dataSet.reduce((accumulator, nb) => accumulator + nb, 0) / dataSet.length
+}
/**
* Computes the median of the given data set.
*/
export const median = (dataSet: number[]): number => {
if (isEmptyArray(dataSet)) {
- return 0;
+ return 0
}
- if (Array.isArray(dataSet) === true && dataSet.length === 1) {
- return dataSet[0];
+ if (Array.isArray(dataSet) && dataSet.length === 1) {
+ return dataSet[0]
}
- const sortedDataSet = dataSet.slice().sort((a, b) => a - b);
+ const sortedDataSet = dataSet.slice().sort((a, b) => a - b)
return (
(sortedDataSet[(sortedDataSet.length - 1) >> 1] + sortedDataSet[sortedDataSet.length >> 1]) / 2
- );
-};
+ )
+}
// TODO: use order statistics tree https://en.wikipedia.org/wiki/Order_statistic_tree
export const nthPercentile = (dataSet: number[], percentile: number): number => {
if (percentile < 0 && percentile > 100) {
- throw new RangeError('Percentile is not between 0 and 100');
+ throw new RangeError('Percentile is not between 0 and 100')
}
if (isEmptyArray(dataSet)) {
- return 0;
+ return 0
}
- const sortedDataSet = dataSet.slice().sort((a, b) => a - b);
+ const sortedDataSet = dataSet.slice().sort((a, b) => a - b)
if (percentile === 0 || sortedDataSet.length === 1) {
- return sortedDataSet[0];
+ return sortedDataSet[0]
}
if (percentile === 100) {
- return sortedDataSet[sortedDataSet.length - 1];
+ return sortedDataSet[sortedDataSet.length - 1]
}
- const percentileIndexBase = (percentile / 100) * (sortedDataSet.length - 1);
- const percentileIndexInteger = Math.floor(percentileIndexBase);
+ const percentileIndexBase = (percentile / 100) * (sortedDataSet.length - 1)
+ const percentileIndexInteger = Math.floor(percentileIndexBase)
if (!isNullOrUndefined(sortedDataSet[percentileIndexInteger + 1])) {
return (
sortedDataSet[percentileIndexInteger] +
(percentileIndexBase - percentileIndexInteger) *
(sortedDataSet[percentileIndexInteger + 1] - sortedDataSet[percentileIndexInteger])
- );
+ )
}
- return sortedDataSet[percentileIndexInteger];
-};
+ return sortedDataSet[percentileIndexInteger]
+}
/**
* Computes the sample standard deviation of the given data set.
*/
export const stdDeviation = (
dataSet: number[],
- dataSetAverage: number = average(dataSet),
+ dataSetAverage: number = average(dataSet)
): number => {
if (isEmptyArray(dataSet)) {
- return 0;
+ return 0
}
if (Array.isArray(dataSet) && dataSet.length === 1) {
- return 0;
+ return 0
}
return Math.sqrt(
dataSet.reduce((accumulator, num) => accumulator + Math.pow(num - dataSetAverage, 2), 0) /
- (dataSet.length - 1),
- );
-};
+ (dataSet.length - 1)
+ )
+}
-import { getRandomValues, randomBytes, randomInt, randomUUID } from 'node:crypto';
-import { env, nextTick } from 'node:process';
+import { getRandomValues, randomBytes, randomInt, randomUUID } from 'node:crypto'
+import { env, nextTick } from 'node:process'
import {
formatDuration,
millisecondsToMinutes,
millisecondsToSeconds,
minutesToSeconds,
- secondsToMilliseconds,
-} from 'date-fns';
+ secondsToMilliseconds
+} from 'date-fns'
-import { Constants } from './Constants.js';
-import { type TimestampedData, WebSocketCloseEventStatusString } from '../types/index.js';
+import { Constants } from './Constants.js'
+import { type TimestampedData, WebSocketCloseEventStatusString } from '../types/index.js'
export const logPrefix = (prefixString = ''): string => {
- return `${new Date().toLocaleString()}${prefixString}`;
-};
+ return `${new Date().toLocaleString()}${prefixString}`
+}
export const generateUUID = (): string => {
- return randomUUID();
-};
+ return randomUUID()
+}
export const validateUUID = (uuid: string): boolean => {
- return /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/.test(
- uuid,
- );
-};
+ return /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/.test(uuid)
+}
export const sleep = async (milliSeconds: number): Promise<NodeJS.Timeout> => {
- return new Promise<NodeJS.Timeout>((resolve) => setTimeout(resolve as () => void, milliSeconds));
-};
+ return await new Promise<NodeJS.Timeout>((resolve) =>
+ setTimeout(resolve as () => void, milliSeconds)
+ )
+}
export const formatDurationMilliSeconds = (duration: number): string => {
- duration = convertToInt(duration);
+ duration = convertToInt(duration)
if (duration < 0) {
- throw new RangeError('Duration cannot be negative');
+ throw new RangeError('Duration cannot be negative')
}
- const days = Math.floor(duration / (24 * 3600 * 1000));
- const hours = Math.floor(millisecondsToHours(duration) - days * 24);
+ const days = Math.floor(duration / (24 * 3600 * 1000))
+ const hours = Math.floor(millisecondsToHours(duration) - days * 24)
const minutes = Math.floor(
- millisecondsToMinutes(duration) - days * 24 * 60 - hoursToMinutes(hours),
- );
+ millisecondsToMinutes(duration) - days * 24 * 60 - hoursToMinutes(hours)
+ )
const seconds = Math.floor(
millisecondsToSeconds(duration) -
days * 24 * 3600 -
hoursToSeconds(hours) -
- minutesToSeconds(minutes),
- );
+ minutesToSeconds(minutes)
+ )
if (days === 0 && hours === 0 && minutes === 0 && seconds === 0) {
- return formatDuration({ seconds }, { zero: true });
+ return formatDuration({ seconds }, { zero: true })
}
return formatDuration({
days,
hours,
minutes,
- seconds,
- });
-};
+ seconds
+ })
+}
export const formatDurationSeconds = (duration: number): string => {
- return formatDurationMilliSeconds(secondsToMilliseconds(duration));
-};
+ return formatDurationMilliSeconds(secondsToMilliseconds(duration))
+}
// More efficient time validation function than the one provided by date-fns
export const isValidTime = (date: unknown): boolean => {
if (typeof date === 'number') {
- return !isNaN(date);
+ return !isNaN(date)
} else if (isDate(date)) {
- return !isNaN(date.getTime());
+ return !isNaN(date.getTime())
}
- return false;
-};
+ return false
+}
export const convertToDate = (
- value: Date | string | number | null | undefined,
+ value: Date | string | number | null | undefined
): Date | null | undefined => {
- if (isNullOrUndefined(value)) {
- return value as null | undefined;
+ if (value == null) {
+ return value
}
if (isDate(value)) {
- return value;
+ return value
}
if (isString(value) || typeof value === 'number') {
- const valueToDate = new Date(value!);
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ const valueToDate = new Date(value)
if (isNaN(valueToDate.getTime())) {
- throw new Error(`Cannot convert to date: '${value!}'`);
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ throw new Error(`Cannot convert to date: '${value}'`)
}
- return valueToDate;
+ return valueToDate
}
-};
+}
export const convertToInt = (value: unknown): number => {
- if (!value) {
- return 0;
+ if (value == null) {
+ return 0
}
- let changedValue: number = value as number;
+ let changedValue: number = value as number
if (Number.isSafeInteger(value)) {
- return value as number;
+ return value as number
}
if (typeof value === 'number') {
- return Math.trunc(value);
+ return Math.trunc(value)
}
if (isString(value)) {
- changedValue = parseInt(value as string);
+ changedValue = parseInt(value as string)
}
if (isNaN(changedValue)) {
- throw new Error(`Cannot convert to integer: '${String(value)}'`);
+ throw new Error(`Cannot convert to integer: '${String(value)}'`)
}
- return changedValue;
-};
+ return changedValue
+}
export const convertToFloat = (value: unknown): number => {
- if (!value) {
- return 0;
+ if (value == null) {
+ return 0
}
- let changedValue: number = value as number;
+ let changedValue: number = value as number
if (isString(value)) {
- changedValue = parseFloat(value as string);
+ changedValue = parseFloat(value as string)
}
if (isNaN(changedValue)) {
- throw new Error(`Cannot convert to float: '${String(value)}'`);
+ throw new Error(`Cannot convert to float: '${String(value)}'`)
}
- return changedValue;
-};
+ return changedValue
+}
export const convertToBoolean = (value: unknown): boolean => {
- let result = false;
+ let result = false
if (value != null) {
// Check the type
if (typeof value === 'boolean') {
- return value;
+ return value
} else if (isString(value) && ((value as string).toLowerCase() === 'true' || value === '1')) {
- result = true;
+ result = true
} else if (typeof value === 'number' && value === 1) {
- result = true;
+ result = true
}
}
- return result;
-};
+ return result
+}
export const getRandomFloat = (max = Number.MAX_VALUE, min = 0): number => {
if (max < min) {
- throw new RangeError('Invalid interval');
+ throw new RangeError('Invalid interval')
}
if (max - min === Infinity) {
- throw new RangeError('Invalid interval');
+ throw new RangeError('Invalid interval')
}
- return (randomBytes(4).readUInt32LE() / 0xffffffff) * (max - min) + min;
-};
+ return (randomBytes(4).readUInt32LE() / 0xffffffff) * (max - min) + min
+}
export const getRandomInteger = (max = Constants.MAX_RANDOM_INTEGER, min = 0): number => {
- max = Math.floor(max);
- if (!isNullOrUndefined(min) && min !== 0) {
- min = Math.ceil(min);
- return Math.floor(randomInt(min, max + 1));
+ max = Math.floor(max)
+ if (min != null && min !== 0) {
+ min = Math.ceil(min)
+ return Math.floor(randomInt(min, max + 1))
}
- return Math.floor(randomInt(max + 1));
-};
+ return Math.floor(randomInt(max + 1))
+}
/**
* Rounds the given number to the given scale.
* @returns The rounded number.
*/
export const roundTo = (numberValue: number, scale: number): number => {
- const roundPower = Math.pow(10, scale);
- return Math.round(numberValue * roundPower * (1 + Number.EPSILON)) / roundPower;
-};
+ const roundPower = Math.pow(10, scale)
+ return Math.round(numberValue * roundPower * (1 + Number.EPSILON)) / roundPower
+}
export const getRandomFloatRounded = (max = Number.MAX_VALUE, min = 0, scale = 2): number => {
- if (min) {
- return roundTo(getRandomFloat(max, min), scale);
+ if (min != null && min !== 0) {
+ return roundTo(getRandomFloat(max, min), scale)
}
- return roundTo(getRandomFloat(max), scale);
-};
+ return roundTo(getRandomFloat(max), scale)
+}
export const getRandomFloatFluctuatedRounded = (
staticValue: number,
fluctuationPercent: number,
- scale = 2,
+ scale = 2
): number => {
if (fluctuationPercent < 0 || fluctuationPercent > 100) {
throw new RangeError(
- `Fluctuation percent must be between 0 and 100. Actual value: ${fluctuationPercent}`,
- );
+ `Fluctuation percent must be between 0 and 100. Actual value: ${fluctuationPercent}`
+ )
}
if (fluctuationPercent === 0) {
- return roundTo(staticValue, scale);
+ return roundTo(staticValue, scale)
}
- const fluctuationRatio = fluctuationPercent / 100;
+ const fluctuationRatio = fluctuationPercent / 100
return getRandomFloatRounded(
staticValue * (1 + fluctuationRatio),
staticValue * (1 - fluctuationRatio),
- scale,
- );
-};
+ scale
+ )
+}
-export const extractTimeSeriesValues = (timeSeries: Array<TimestampedData>): number[] => {
- return timeSeries.map((timeSeriesItem) => timeSeriesItem.value);
-};
+export const extractTimeSeriesValues = (timeSeries: TimestampedData[]): number[] => {
+ return timeSeries.map((timeSeriesItem) => timeSeriesItem.value)
+}
export const isObject = (item: unknown): boolean => {
- return (
- isNullOrUndefined(item) === false && typeof item === 'object' && Array.isArray(item) === false
- );
-};
+ return !isNullOrUndefined(item) && typeof item === 'object' && !Array.isArray(item)
+}
type CloneableData =
| number
| undefined
| Date
| CloneableData[]
- | { [key: string]: CloneableData };
+ | { [key: string]: CloneableData }
-type FormatKey = (key: string) => string;
+type FormatKey = (key: string) => string
const deepClone = <I extends CloneableData, O extends CloneableData = I>(
value: I,
formatKey?: FormatKey,
- refs: Map<I, O> = new Map<I, O>(),
+ refs: Map<I, O> = new Map<I, O>()
): O => {
- const ref = refs.get(value);
+ const ref = refs.get(value)
if (ref !== undefined) {
- return ref;
+ return ref
}
if (Array.isArray(value)) {
- const clone: CloneableData[] = [];
- refs.set(value, clone as O);
+ const clone: CloneableData[] = []
+ refs.set(value, clone as O)
for (let i = 0; i < value.length; i++) {
- clone[i] = deepClone(value[i], formatKey, refs);
+ clone[i] = deepClone(value[i], formatKey, refs)
}
- return clone as O;
+ return clone as O
}
if (value instanceof Date) {
- return new Date(value.valueOf()) as O;
+ return new Date(value.valueOf()) as O
}
if (typeof value !== 'object' || value === null) {
- return value as unknown as O;
+ return value as unknown as O
}
- const clone: Record<string, CloneableData> = {};
- refs.set(value, clone as O);
+ const clone: Record<string, CloneableData> = {}
+ refs.set(value, clone as O)
for (const key of Object.keys(value)) {
clone[typeof formatKey === 'function' ? formatKey(key) : key] = deepClone(
value[key],
formatKey,
- refs,
- );
+ refs
+ )
}
- return clone as O;
-};
+ return clone as O
+}
export const cloneObject = <T>(object: T): T => {
- return deepClone(object as CloneableData) as T;
-};
+ return deepClone(object as CloneableData) as T
+}
export const hasOwnProp = (object: unknown, property: PropertyKey): boolean => {
- return isObject(object) && Object.hasOwn(object as object, property);
-};
+ return isObject(object) && Object.hasOwn(object as object, property)
+}
export const isCFEnvironment = (): boolean => {
- return !isNullOrUndefined(env.VCAP_APPLICATION);
-};
+ return !isNullOrUndefined(env.VCAP_APPLICATION)
+}
export const isIterable = <T>(obj: T): boolean => {
- return !isNullOrUndefined(obj) ? typeof obj[Symbol.iterator as keyof T] === 'function' : false;
-};
+ return !isNullOrUndefined(obj) ? typeof obj[Symbol.iterator as keyof T] === 'function' : false
+}
const isString = (value: unknown): boolean => {
- return typeof value === 'string';
-};
+ return typeof value === 'string'
+}
export const isEmptyString = (value: unknown): boolean => {
- return isNullOrUndefined(value) || (isString(value) && (value as string).trim().length === 0);
-};
+ return isNullOrUndefined(value) || (isString(value) && (value as string).trim().length === 0)
+}
export const isNotEmptyString = (value: unknown): boolean => {
- return isString(value) && (value as string).trim().length > 0;
-};
+ return isString(value) && (value as string).trim().length > 0
+}
export const isUndefined = (value: unknown): boolean => {
- return value === undefined;
-};
+ return value === undefined
+}
export const isNullOrUndefined = (value: unknown): boolean => {
- return value == null;
-};
+ return value == null
+}
export const isEmptyArray = (object: unknown): boolean => {
- return Array.isArray(object) && object.length === 0;
-};
+ return Array.isArray(object) && object.length === 0
+}
export const isNotEmptyArray = (object: unknown): boolean => {
- return Array.isArray(object) && object.length > 0;
-};
+ return Array.isArray(object) && object.length > 0
+}
export const isEmptyObject = (obj: object): boolean => {
if (obj?.constructor !== Object) {
- return false;
+ return false
}
// Iterates over the keys of an object, if
// any exist, return false.
+ // eslint-disable-next-line no-unreachable-loop
for (const _ in obj) {
- return false;
+ return false
}
- return true;
-};
+ return true
+}
export const insertAt = (str: string, subStr: string, pos: number): string =>
- `${str.slice(0, pos)}${subStr}${str.slice(pos)}`;
+ `${str.slice(0, pos)}${subStr}${str.slice(pos)}`
/**
* Computes the retry delay in milliseconds using an exponential backoff algorithm.
* @returns delay in milliseconds
*/
export const exponentialDelay = (retryNumber = 0, delayFactor = 100): number => {
- const delay = Math.pow(2, retryNumber) * delayFactor;
- const randomSum = delay * 0.2 * secureRandom(); // 0-20% of the delay
- return delay + randomSum;
-};
+ const delay = Math.pow(2, retryNumber) * delayFactor
+ const randomSum = delay * 0.2 * secureRandom() // 0-20% of the delay
+ return delay + randomSum
+}
/**
* Generates a cryptographically secure random number in the [0,1[ range
* @returns A number in the [0,1[ range
*/
export const secureRandom = (): number => {
- return getRandomValues(new Uint32Array(1))[0] / 0x100000000;
-};
+ return getRandomValues(new Uint32Array(1))[0] / 0x100000000
+}
export const JSONStringifyWithMapSupport = (
- obj: Record<string, unknown> | Record<string, unknown>[] | Map<unknown, unknown>,
- space?: number,
+ obj: Record<string, unknown> | Array<Record<string, unknown>> | Map<unknown, unknown>,
+ space?: number
): string => {
return JSON.stringify(
obj,
if (value instanceof Map) {
return {
dataType: 'Map',
- value: [...value],
- };
+ value: [...value]
+ }
}
- return value;
+ return value
},
- space,
- );
-};
+ space
+ )
+}
/**
* Converts websocket error code to human readable string message
*/
export const getWebSocketCloseEventStatusString = (code: number): string => {
if (code >= 0 && code <= 999) {
- return '(Unused)';
+ return '(Unused)'
} else if (code >= 1016) {
if (code <= 1999) {
- return '(For WebSocket standard)';
+ return '(For WebSocket standard)'
} else if (code <= 2999) {
- return '(For WebSocket extensions)';
+ return '(For WebSocket extensions)'
} else if (code <= 3999) {
- return '(For libraries and frameworks)';
+ return '(For libraries and frameworks)'
} else if (code <= 4999) {
- return '(For applications)';
+ return '(For applications)'
}
}
if (
!isUndefined(
- WebSocketCloseEventStatusString[code as keyof typeof WebSocketCloseEventStatusString],
+ WebSocketCloseEventStatusString[code as keyof typeof WebSocketCloseEventStatusString]
)
) {
- return WebSocketCloseEventStatusString[code as keyof typeof WebSocketCloseEventStatusString];
+ return WebSocketCloseEventStatusString[code as keyof typeof WebSocketCloseEventStatusString]
}
- return '(Unknown)';
-};
+ return '(Unknown)'
+}
export const isArraySorted = <T>(array: T[], compareFn: (a: T, b: T) => number): boolean => {
for (let index = 0; index < array.length - 1; ++index) {
if (compareFn(array[index], array[index + 1]) > 0) {
- return false;
+ return false
}
}
- return true;
-};
+ return true
+}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const once = <T, A extends any[], R>(
fn: (...args: A) => R,
- context: T,
+ context: T
): ((...args: A) => R) => {
- let result: R;
+ let result: R
return (...args: A) => {
- if (fn) {
- result = fn.apply<T, A, R>(context, args);
- (fn as unknown as undefined) = (context as unknown as undefined) = undefined;
+ if (fn != null) {
+ result = fn.apply<T, A, R>(context, args)
+ ;(fn as unknown as undefined) = (context as unknown as undefined) = undefined
}
- return result;
- };
-};
+ return result
+ }
+}
export const min = (...args: number[]): number =>
- args.reduce((minimum, num) => (minimum < num ? minimum : num), Infinity);
+ args.reduce((minimum, num) => (minimum < num ? minimum : num), Infinity)
export const max = (...args: number[]): number =>
- args.reduce((maximum, num) => (maximum > num ? maximum : num), -Infinity);
+ args.reduce((maximum, num) => (maximum > num ? maximum : num), -Infinity)
export const throwErrorInNextTick = (error: Error): void => {
nextTick(() => {
- throw error;
- });
-};
+ throw error
+ })
+}
-export { ACElectricUtils, DCElectricUtils } from './ElectricUtils.js';
-export { AsyncLock, AsyncLockType } from './AsyncLock.js';
+export { ACElectricUtils, DCElectricUtils } from './ElectricUtils.js'
+export { AsyncLock, AsyncLockType } from './AsyncLock.js'
export {
OutputFormat,
buildChargingStationAutomaticTransactionGeneratorConfiguration,
buildConnectorsStatus,
- buildEvsesStatus,
-} from './ChargingStationConfigurationUtils.js';
-export { CircularArray } from './CircularArray.js';
-export { Configuration } from './Configuration.js';
-export { Constants } from './Constants.js';
+ buildEvsesStatus
+} from './ChargingStationConfigurationUtils.js'
+export { CircularArray } from './CircularArray.js'
+export { Configuration } from './Configuration.js'
+export { Constants } from './Constants.js'
export {
handleFileException,
handleUncaughtException,
handleUnhandledRejection,
handleSendMessageError,
- setDefaultErrorParams,
-} from './ErrorUtils.js';
-export { watchJsonFile } from './FileUtils.js';
+ setDefaultErrorParams
+} from './ErrorUtils.js'
+export { watchJsonFile } from './FileUtils.js'
export {
buildPerformanceStatisticsMessage,
buildUpdatedMessage,
buildStartedMessage,
- buildStoppedMessage,
-} from './MessageChannelUtils.js';
+ buildStoppedMessage
+} from './MessageChannelUtils.js'
export {
JSONStringifyWithMapSupport,
cloneObject,
roundTo,
secureRandom,
sleep,
- validateUUID,
-} from './Utils.js';
-export { average, median, nthPercentile, stdDeviation } from './StatisticUtils.js';
-export { logger } from './Logger.js';
+ validateUUID
+} from './Utils.js'
+export { average, median, nthPercentile, stdDeviation } from './StatisticUtils.js'
+export { logger } from './Logger.js'
-import type { EventEmitterAsyncResource } from 'node:events';
-import { existsSync } from 'node:fs';
+import type { EventEmitterAsyncResource } from 'node:events'
+import { existsSync } from 'node:fs'
-import type { PoolInfo } from 'poolifier';
+import type { PoolInfo } from 'poolifier'
-import type { SetInfo, WorkerData, WorkerOptions } from './WorkerTypes.js';
-import { defaultErrorHandler, defaultExitHandler } from './WorkerUtils.js';
+import type { SetInfo, WorkerData, WorkerOptions } from './WorkerTypes.js'
export abstract class WorkerAbstract<T extends WorkerData> {
- protected readonly workerScript: string;
- protected readonly workerOptions: WorkerOptions;
- public abstract readonly info: PoolInfo | SetInfo;
- public abstract readonly size: number;
- public abstract readonly maxElementsPerWorker: number | undefined;
- public abstract readonly emitter: EventEmitterAsyncResource | undefined;
+ protected readonly workerScript: string
+ protected readonly workerOptions: WorkerOptions
+ public abstract readonly info: PoolInfo | SetInfo
+ public abstract readonly size: number
+ public abstract readonly maxElementsPerWorker: number | undefined
+ public abstract readonly emitter: EventEmitterAsyncResource | undefined
/**
* `WorkerAbstract` constructor.
* @param workerScript -
* @param workerOptions -
*/
- constructor(workerScript: string, workerOptions: WorkerOptions) {
+ constructor (workerScript: string, workerOptions: WorkerOptions) {
if (workerScript == null) {
- throw new TypeError('Worker script is not defined');
+ throw new TypeError('Worker script is not defined')
}
if (typeof workerScript !== 'string') {
- throw new TypeError('Worker script must be a string');
+ throw new TypeError('Worker script must be a string')
}
if (workerScript.trim().length === 0) {
- throw new Error('Worker script is an empty string');
+ throw new Error('Worker script is an empty string')
}
if (!existsSync(workerScript)) {
- throw new Error('Worker script file does not exist');
+ throw new Error('Worker script file does not exist')
}
- this.workerScript = workerScript;
- this.workerOptions = workerOptions;
- this.workerOptions.poolOptions!.errorHandler =
- this.workerOptions.poolOptions?.errorHandler ?? defaultErrorHandler;
- this.workerOptions.poolOptions!.exitHandler =
- this.workerOptions.poolOptions?.exitHandler ?? defaultExitHandler;
+ this.workerScript = workerScript
+ this.workerOptions = workerOptions
}
/**
* Starts the worker pool/set.
*/
- public abstract start(): Promise<void>;
+ public abstract start (): Promise<void>
/**
* Stops the worker pool/set.
*/
- public abstract stop(): Promise<void>;
+ public abstract stop (): Promise<void>
/**
* Adds a task element to the worker pool/set.
*
* @param elementData -
*/
- public abstract addElement(elementData: T): Promise<void>;
+ public abstract addElement (elementData: T): Promise<void>
}
-import { availableParallelism } from 'poolifier';
+import { availableParallelism } from 'poolifier'
-import type { WorkerOptions } from './WorkerTypes.js';
+import type { WorkerOptions } from './WorkerTypes.js'
+import { defaultErrorHandler, defaultExitHandler } from './WorkerUtils.js'
export const EMPTY_FUNCTION = Object.freeze(() => {
/* This is intentional */
-});
+})
-export const workerSetVersion = '1.0.1';
+export const workerSetVersion = '1.0.1'
-export const DEFAULT_ELEMENT_START_DELAY = 0;
-export const DEFAULT_WORKER_START_DELAY = 500;
-export const DEFAULT_POOL_MIN_SIZE = Math.floor(availableParallelism() / 2);
-export const DEFAULT_POOL_MAX_SIZE = Math.round(availableParallelism() * 1.5);
-export const DEFAULT_ELEMENTS_PER_WORKER = 1;
+export const DEFAULT_ELEMENT_START_DELAY = 0
+export const DEFAULT_WORKER_START_DELAY = 500
+export const DEFAULT_POOL_MIN_SIZE = Math.floor(availableParallelism() / 2)
+export const DEFAULT_POOL_MAX_SIZE = Math.round(availableParallelism() * 1.5)
+export const DEFAULT_ELEMENTS_PER_WORKER = 1
export const DEFAULT_WORKER_OPTIONS: WorkerOptions = Object.freeze({
workerStartDelay: DEFAULT_WORKER_START_DELAY,
poolOptions: {
enableEvents: true,
restartWorkerOnError: true,
- },
-});
+ errorHandler: defaultErrorHandler,
+ exitHandler: defaultExitHandler
+ }
+})
-import type { EventEmitterAsyncResource } from 'node:events';
+import type { EventEmitterAsyncResource } from 'node:events'
-import { DynamicThreadPool, type PoolInfo } from 'poolifier';
+import { DynamicThreadPool, type PoolInfo } from 'poolifier'
-import { WorkerAbstract } from './WorkerAbstract.js';
-import type { WorkerData, WorkerOptions } from './WorkerTypes.js';
-import { randomizeDelay, sleep } from './WorkerUtils.js';
+import { WorkerAbstract } from './WorkerAbstract.js'
+import type { WorkerData, WorkerOptions } from './WorkerTypes.js'
+import { randomizeDelay, sleep } from './WorkerUtils.js'
export class WorkerDynamicPool extends WorkerAbstract<WorkerData> {
- private readonly pool: DynamicThreadPool<WorkerData>;
+ private readonly pool: DynamicThreadPool<WorkerData>
/**
* Creates a new `WorkerDynamicPool`.
* @param workerScript -
* @param workerOptions -
*/
- constructor(workerScript: string, workerOptions: WorkerOptions) {
- super(workerScript, workerOptions);
+ constructor (workerScript: string, workerOptions: WorkerOptions) {
+ super(workerScript, workerOptions)
this.pool = new DynamicThreadPool<WorkerData>(
this.workerOptions.poolMinSize,
this.workerOptions.poolMaxSize,
this.workerScript,
- this.workerOptions.poolOptions,
- );
+ this.workerOptions.poolOptions
+ )
}
- get info(): PoolInfo {
- return this.pool.info;
+ get info (): PoolInfo {
+ return this.pool.info
}
- get size(): number {
- return this.pool.info.workerNodes;
+ get size (): number {
+ return this.pool.info.workerNodes
}
- get maxElementsPerWorker(): number | undefined {
- return undefined;
+ get maxElementsPerWorker (): number | undefined {
+ return undefined
}
- get emitter(): EventEmitterAsyncResource | undefined {
- return this.pool?.emitter;
+ get emitter (): EventEmitterAsyncResource | undefined {
+ return this.pool?.emitter
}
/** @inheritDoc */
- public async start(): Promise<void> {
+ public async start (): Promise<void> {
// This is intentional
}
/** @inheritDoc */
- public async stop(): Promise<void> {
- return this.pool.destroy();
+ public async stop (): Promise<void> {
+ await this.pool.destroy()
}
/** @inheritDoc */
- public async addElement(elementData: WorkerData): Promise<void> {
- await this.pool.execute(elementData);
+ public async addElement (elementData: WorkerData): Promise<void> {
+ await this.pool.execute(elementData)
// Start element sequentially to optimize memory at startup
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.workerOptions.elementStartDelay! > 0 &&
- (await sleep(randomizeDelay(this.workerOptions.elementStartDelay!)));
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ (await sleep(randomizeDelay(this.workerOptions.elementStartDelay!)))
}
}
-import { isMainThread } from 'node:worker_threads';
+import { isMainThread } from 'node:worker_threads'
-import type { WorkerAbstract } from './WorkerAbstract.js';
-import { DEFAULT_WORKER_OPTIONS } from './WorkerConstants.js';
-import { WorkerDynamicPool } from './WorkerDynamicPool.js';
-import { WorkerFixedPool } from './WorkerFixedPool.js';
-import { WorkerSet } from './WorkerSet.js';
-import { type WorkerData, type WorkerOptions, WorkerProcessType } from './WorkerTypes.js';
+import type { WorkerAbstract } from './WorkerAbstract.js'
+import { DEFAULT_WORKER_OPTIONS } from './WorkerConstants.js'
+import { WorkerDynamicPool } from './WorkerDynamicPool.js'
+import { WorkerFixedPool } from './WorkerFixedPool.js'
+import { WorkerSet } from './WorkerSet.js'
+import { type WorkerData, type WorkerOptions, WorkerProcessType } from './WorkerTypes.js'
+// eslint-disable-next-line @typescript-eslint/no-extraneous-class
export class WorkerFactory {
- private constructor() {
+ private constructor () {
// This is intentional
}
public static getWorkerImplementation<T extends WorkerData>(
workerScript: string,
workerProcessType: WorkerProcessType,
- workerOptions?: WorkerOptions,
+ workerOptions?: WorkerOptions
): WorkerAbstract<T> | undefined {
if (!isMainThread) {
- throw new Error('Cannot get a worker implementation outside the main thread');
+ throw new Error('Cannot get a worker implementation outside the main thread')
}
- workerOptions = { ...DEFAULT_WORKER_OPTIONS, ...workerOptions };
- let workerImplementation: WorkerAbstract<T>;
+ workerOptions = { ...DEFAULT_WORKER_OPTIONS, ...workerOptions }
+ let workerImplementation: WorkerAbstract<T>
switch (workerProcessType) {
case WorkerProcessType.workerSet:
- workerImplementation = new WorkerSet(workerScript, workerOptions);
- break;
+ workerImplementation = new WorkerSet(workerScript, workerOptions)
+ break
case WorkerProcessType.fixedPool:
- workerImplementation = new WorkerFixedPool(workerScript, workerOptions);
- break;
+ workerImplementation = new WorkerFixedPool(workerScript, workerOptions)
+ break
case WorkerProcessType.dynamicPool:
- workerImplementation = new WorkerDynamicPool(workerScript, workerOptions);
- break;
+ workerImplementation = new WorkerDynamicPool(workerScript, workerOptions)
+ break
default:
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
- throw new Error(`Worker implementation type '${workerProcessType}' not found`);
+ throw new Error(`Worker implementation type '${workerProcessType}' not found`)
}
- return workerImplementation;
+ return workerImplementation
}
}
-import type { EventEmitterAsyncResource } from 'node:events';
+import type { EventEmitterAsyncResource } from 'node:events'
-import { FixedThreadPool, type PoolInfo } from 'poolifier';
+import { FixedThreadPool, type PoolInfo } from 'poolifier'
-import { WorkerAbstract } from './WorkerAbstract.js';
-import type { WorkerData, WorkerOptions } from './WorkerTypes.js';
-import { randomizeDelay, sleep } from './WorkerUtils.js';
+import { WorkerAbstract } from './WorkerAbstract.js'
+import type { WorkerData, WorkerOptions } from './WorkerTypes.js'
+import { randomizeDelay, sleep } from './WorkerUtils.js'
export class WorkerFixedPool extends WorkerAbstract<WorkerData> {
- private readonly pool: FixedThreadPool<WorkerData>;
+ private readonly pool: FixedThreadPool<WorkerData>
/**
* Creates a new `WorkerFixedPool`.
* @param workerScript -
* @param workerOptions -
*/
- constructor(workerScript: string, workerOptions: WorkerOptions) {
- super(workerScript, workerOptions);
+ constructor (workerScript: string, workerOptions: WorkerOptions) {
+ super(workerScript, workerOptions)
this.pool = new FixedThreadPool(
this.workerOptions.poolMaxSize,
this.workerScript,
- this.workerOptions.poolOptions,
- );
+ this.workerOptions.poolOptions
+ )
}
- get info(): PoolInfo {
- return this.pool.info;
+ get info (): PoolInfo {
+ return this.pool.info
}
- get size(): number {
- return this.pool.info.workerNodes;
+ get size (): number {
+ return this.pool.info.workerNodes
}
- get maxElementsPerWorker(): number | undefined {
- return undefined;
+ get maxElementsPerWorker (): number | undefined {
+ return undefined
}
- get emitter(): EventEmitterAsyncResource | undefined {
- return this.pool?.emitter;
+ get emitter (): EventEmitterAsyncResource | undefined {
+ return this.pool?.emitter
}
/** @inheritDoc */
- public async start(): Promise<void> {
+ public async start (): Promise<void> {
// This is intentional
}
/** @inheritDoc */
- public async stop(): Promise<void> {
- return this.pool.destroy();
+ public async stop (): Promise<void> {
+ await this.pool.destroy()
}
/** @inheritDoc */
- public async addElement(elementData: WorkerData): Promise<void> {
- await this.pool.execute(elementData);
+ public async addElement (elementData: WorkerData): Promise<void> {
+ await this.pool.execute(elementData)
// Start element sequentially to optimize memory at startup
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.workerOptions.elementStartDelay! > 0 &&
- (await sleep(randomizeDelay(this.workerOptions.elementStartDelay!)));
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ (await sleep(randomizeDelay(this.workerOptions.elementStartDelay!)))
}
}
// Partial Copyright Jerome Benoit. 2021-2023. All Rights Reserved.
-import { EventEmitterAsyncResource } from 'node:events';
-import { SHARE_ENV, Worker } from 'node:worker_threads';
+import { EventEmitterAsyncResource } from 'node:events'
+import { SHARE_ENV, Worker } from 'node:worker_threads'
-import { WorkerAbstract } from './WorkerAbstract.js';
-import { EMPTY_FUNCTION, workerSetVersion } from './WorkerConstants.js';
+import { WorkerAbstract } from './WorkerAbstract.js'
+import { EMPTY_FUNCTION, workerSetVersion } from './WorkerConstants.js'
import {
type SetInfo,
type WorkerData,
WorkerMessageEvents,
type WorkerOptions,
type WorkerSetElement,
- WorkerSetEvents,
-} from './WorkerTypes.js';
-import { randomizeDelay, sleep } from './WorkerUtils.js';
+ WorkerSetEvents
+} from './WorkerTypes.js'
+import { randomizeDelay, sleep } from './WorkerUtils.js'
export class WorkerSet extends WorkerAbstract<WorkerData> {
- public readonly emitter: EventEmitterAsyncResource | undefined;
- private readonly workerSet: Set<WorkerSetElement>;
- private started: boolean;
- private workerStartup: boolean;
+ public readonly emitter: EventEmitterAsyncResource | undefined
+ private readonly workerSet: Set<WorkerSetElement>
+ private started: boolean
+ private workerStartup: boolean
/**
* Creates a new `WorkerSet`.
* @param workerScript -
* @param workerOptions -
*/
- constructor(workerScript: string, workerOptions: WorkerOptions) {
- super(workerScript, workerOptions);
+ constructor (workerScript: string, workerOptions: WorkerOptions) {
+ super(workerScript, workerOptions)
if (this.workerOptions.elementsPerWorker == null) {
- throw new TypeError('Elements per worker is not defined');
+ throw new TypeError('Elements per worker is not defined')
}
if (!Number.isSafeInteger(this.workerOptions.elementsPerWorker)) {
- throw new TypeError('Elements per worker must be an integer');
+ throw new TypeError('Elements per worker must be an integer')
}
if (this.workerOptions.elementsPerWorker <= 0) {
- throw new RangeError('Elements per worker must be greater than zero');
+ throw new RangeError('Elements per worker must be greater than zero')
}
- this.workerSet = new Set<WorkerSetElement>();
- if (this.workerOptions.poolOptions?.enableEvents) {
- this.emitter = new EventEmitterAsyncResource({ name: 'workerset' });
+ this.workerSet = new Set<WorkerSetElement>()
+ if (this.workerOptions.poolOptions?.enableEvents != null) {
+ this.emitter = new EventEmitterAsyncResource({ name: 'workerset' })
}
- this.started = false;
- this.workerStartup = false;
+ this.started = false
+ this.workerStartup = false
}
- get info(): SetInfo {
+ get info (): SetInfo {
return {
version: workerSetVersion,
type: 'set',
size: this.size,
elementsExecuting: [...this.workerSet].reduce(
(accumulator, workerSetElement) => accumulator + workerSetElement.numberOfWorkerElements,
- 0,
+ 0
),
- elementsPerWorker: this.maxElementsPerWorker!,
- };
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ elementsPerWorker: this.maxElementsPerWorker!
+ }
}
- get size(): number {
- return this.workerSet.size;
+ get size (): number {
+ return this.workerSet.size
}
- get maxElementsPerWorker(): number | undefined {
- return this.workerOptions.elementsPerWorker;
+ get maxElementsPerWorker (): number | undefined {
+ return this.workerOptions.elementsPerWorker
}
/** @inheritDoc */
- public async start(): Promise<void> {
- this.addWorkerSetElement();
+ public async start (): Promise<void> {
+ this.addWorkerSetElement()
// Add worker set element sequentially to optimize memory at startup
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.workerOptions.workerStartDelay! > 0 &&
- (await sleep(randomizeDelay(this.workerOptions.workerStartDelay!)));
- this.emitter?.emit(WorkerSetEvents.started, this.info);
- this.started = true;
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ (await sleep(randomizeDelay(this.workerOptions.workerStartDelay!)))
+ this.emitter?.emit(WorkerSetEvents.started, this.info)
+ this.started = true
}
/** @inheritDoc */
- public async stop(): Promise<void> {
+ public async stop (): Promise<void> {
for (const workerSetElement of this.workerSet) {
- const worker = workerSetElement.worker;
+ const worker = workerSetElement.worker
const waitWorkerExit = new Promise<void>((resolve) => {
worker.once('exit', () => {
- resolve();
- });
- });
- await worker.terminate();
- await waitWorkerExit;
- this.emitter?.emit(WorkerSetEvents.stopped, this.info);
- this.emitter?.emitDestroy();
- this.emitter?.removeAllListeners();
- this.started = false;
+ resolve()
+ })
+ })
+ await worker.terminate()
+ await waitWorkerExit
+ this.emitter?.emit(WorkerSetEvents.stopped, this.info)
+ this.emitter?.emitDestroy()
+ this.emitter?.removeAllListeners()
+ this.started = false
}
}
/** @inheritDoc */
- public async addElement(elementData: WorkerData): Promise<void> {
+ public async addElement (elementData: WorkerData): Promise<void> {
if (!this.started) {
- throw new Error('Cannot add a WorkerSet element: not started');
+ throw new Error('Cannot add a WorkerSet element: not started')
}
if (this.workerSet == null) {
- throw new Error("Cannot add a WorkerSet element: 'workerSet' property does not exist");
+ throw new Error("Cannot add a WorkerSet element: 'workerSet' property does not exist")
}
- const workerSetElement = await this.getWorkerSetElement();
+ const workerSetElement = await this.getWorkerSetElement()
workerSetElement.worker.postMessage({
event: WorkerMessageEvents.startWorkerElement,
- data: elementData,
- });
- ++workerSetElement.numberOfWorkerElements;
+ data: elementData
+ })
+ ++workerSetElement.numberOfWorkerElements
// Add element sequentially to optimize memory at startup
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
if (this.workerOptions.elementStartDelay! > 0) {
- await sleep(randomizeDelay(this.workerOptions.elementStartDelay!));
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ await sleep(randomizeDelay(this.workerOptions.elementStartDelay!))
}
}
/**
* Adds a new `WorkerSetElement`.
*/
- private addWorkerSetElement(): WorkerSetElement {
- this.workerStartup = true;
+ private addWorkerSetElement (): WorkerSetElement {
+ this.workerStartup = true
const worker = new Worker(this.workerScript, {
env: SHARE_ENV,
- ...this.workerOptions.poolOptions?.workerOptions,
- });
- worker.on('message', this.workerOptions.poolOptions?.messageHandler ?? EMPTY_FUNCTION);
+ ...this.workerOptions.poolOptions?.workerOptions
+ })
+ worker.on('message', this.workerOptions.poolOptions?.messageHandler ?? EMPTY_FUNCTION)
worker.on('message', (message: WorkerMessage<WorkerData>) => {
if (message.event === WorkerMessageEvents.startedWorkerElement) {
- this.emitter?.emit(WorkerSetEvents.elementStarted, this.info);
+ this.emitter?.emit(WorkerSetEvents.elementStarted, this.info)
} else if (message.event === WorkerMessageEvents.startWorkerElementError) {
- this.emitter?.emit(WorkerSetEvents.elementError, message.data);
+ this.emitter?.emit(WorkerSetEvents.elementError, message.data)
}
- });
- worker.on('error', this.workerOptions.poolOptions?.errorHandler ?? EMPTY_FUNCTION);
+ })
+ worker.on('error', this.workerOptions.poolOptions?.errorHandler ?? EMPTY_FUNCTION)
worker.on('error', (error) => {
- this.emitter?.emit(WorkerSetEvents.error, error);
+ this.emitter?.emit(WorkerSetEvents.error, error)
if (
- this.workerOptions.poolOptions?.restartWorkerOnError &&
+ this.workerOptions.poolOptions?.restartWorkerOnError === true &&
this.started &&
!this.workerStartup
) {
- this.addWorkerSetElement();
+ this.addWorkerSetElement()
}
- });
- worker.on('online', this.workerOptions.poolOptions?.onlineHandler ?? EMPTY_FUNCTION);
- worker.on('exit', this.workerOptions.poolOptions?.exitHandler ?? EMPTY_FUNCTION);
- worker.once('exit', () =>
- this.removeWorkerSetElement(this.getWorkerSetElementByWorker(worker)!),
- );
- const workerSetElement: WorkerSetElement = { worker, numberOfWorkerElements: 0 };
- this.workerSet.add(workerSetElement);
- this.workerStartup = false;
- return workerSetElement;
+ })
+ worker.on('online', this.workerOptions.poolOptions?.onlineHandler ?? EMPTY_FUNCTION)
+ worker.on('exit', this.workerOptions.poolOptions?.exitHandler ?? EMPTY_FUNCTION)
+ worker.once('exit', () => {
+ this.removeWorkerSetElement(this.getWorkerSetElementByWorker(worker))
+ })
+ const workerSetElement: WorkerSetElement = { worker, numberOfWorkerElements: 0 }
+ this.workerSet.add(workerSetElement)
+ this.workerStartup = false
+ return workerSetElement
}
- private removeWorkerSetElement(workerSetElement: WorkerSetElement): void {
- this.workerSet.delete(workerSetElement);
+ private removeWorkerSetElement (workerSetElement: WorkerSetElement | undefined): void {
+ if (workerSetElement == null) {
+ return
+ }
+ this.workerSet.delete(workerSetElement)
}
- private async getWorkerSetElement(): Promise<WorkerSetElement> {
- let chosenWorkerSetElement: WorkerSetElement | undefined;
+ private async getWorkerSetElement (): Promise<WorkerSetElement> {
+ let chosenWorkerSetElement: WorkerSetElement | undefined
for (const workerSetElement of this.workerSet) {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
if (workerSetElement.numberOfWorkerElements < this.workerOptions.elementsPerWorker!) {
- chosenWorkerSetElement = workerSetElement;
- break;
+ chosenWorkerSetElement = workerSetElement
+ break
}
}
- if (!chosenWorkerSetElement) {
- chosenWorkerSetElement = this.addWorkerSetElement();
+ if (chosenWorkerSetElement == null) {
+ chosenWorkerSetElement = this.addWorkerSetElement()
// Add worker set element sequentially to optimize memory at startup
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.workerOptions.workerStartDelay! > 0 &&
- (await sleep(randomizeDelay(this.workerOptions.workerStartDelay!)));
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ (await sleep(randomizeDelay(this.workerOptions.workerStartDelay!)))
}
- return chosenWorkerSetElement;
+ return chosenWorkerSetElement
}
- private getWorkerSetElementByWorker(worker: Worker): WorkerSetElement | undefined {
- let workerSetElt: WorkerSetElement | undefined;
+ private getWorkerSetElementByWorker (worker: Worker): WorkerSetElement | undefined {
+ let workerSetElt: WorkerSetElement | undefined
for (const workerSetElement of this.workerSet) {
if (workerSetElement.worker.threadId === worker.threadId) {
- workerSetElt = workerSetElement;
- break;
+ workerSetElt = workerSetElement
+ break
}
}
- return workerSetElt;
+ return workerSetElt
}
}
-import type { Worker } from 'node:worker_threads';
+import type { Worker } from 'node:worker_threads'
-import { type PoolEvent, PoolEvents, type ThreadPoolOptions } from 'poolifier';
+import { type PoolEvent, PoolEvents, type ThreadPoolOptions } from 'poolifier'
export enum WorkerProcessType {
workerSet = 'workerSet',
/** @experimental */
dynamicPool = 'dynamicPool',
- fixedPool = 'fixedPool',
+ fixedPool = 'fixedPool'
}
export interface SetInfo {
- version: string;
- type: string;
- worker: string;
- size: number;
- elementsExecuting: number;
- elementsPerWorker: number;
+ version: string
+ type: string
+ worker: string
+ size: number
+ elementsExecuting: number
+ elementsPerWorker: number
}
export enum WorkerSetEvents {
stopped = 'stopped',
error = 'error',
elementStarted = 'elementStarted',
- elementError = 'elementError',
+ elementError = 'elementError'
}
export const WorkerEvents = {
...PoolEvents,
- ...WorkerSetEvents,
-} as const;
-export type WorkerEvents = PoolEvent | WorkerSetEvents;
+ ...WorkerSetEvents
+} as const
+// eslint-disable-next-line @typescript-eslint/no-redeclare
+export type WorkerEvents = PoolEvent | WorkerSetEvents
export interface WorkerOptions {
- workerStartDelay?: number;
- elementStartDelay?: number;
- poolMaxSize: number;
- poolMinSize: number;
- elementsPerWorker?: number;
- poolOptions?: ThreadPoolOptions;
+ workerStartDelay?: number
+ elementStartDelay?: number
+ poolMaxSize: number
+ poolMinSize: number
+ elementsPerWorker?: number
+ poolOptions?: ThreadPoolOptions
}
-export type WorkerData = Record<string, unknown>;
+export type WorkerData = Record<string, unknown>
export interface WorkerSetElement {
- worker: Worker;
- numberOfWorkerElements: number;
+ worker: Worker
+ numberOfWorkerElements: number
}
export interface WorkerMessage<T extends WorkerData> {
- event: WorkerMessageEvents;
- data: T;
+ event: WorkerMessageEvents
+ data: T
}
export enum WorkerMessageEvents {
startWorkerElement = 'startWorkerElement',
startWorkerElementError = 'startWorkerElementError',
- startedWorkerElement = 'startedWorkerElement',
+ startedWorkerElement = 'startedWorkerElement'
}
-import { getRandomValues } from 'node:crypto';
+import { getRandomValues } from 'node:crypto'
-import chalk from 'chalk';
+import chalk from 'chalk'
export const sleep = async (milliSeconds: number): Promise<NodeJS.Timeout> => {
- return new Promise<NodeJS.Timeout>((resolve) => setTimeout(resolve as () => void, milliSeconds));
-};
+ return await new Promise<NodeJS.Timeout>((resolve) =>
+ setTimeout(resolve as () => void, milliSeconds)
+ )
+}
export const defaultExitHandler = (code: number): void => {
if (code === 0) {
- console.info(chalk.green('Worker exited successfully'));
+ console.info(chalk.green('Worker exited successfully'))
} else if (code === 1) {
- console.info(chalk.green('Worker terminated successfully'));
+ console.info(chalk.green('Worker terminated successfully'))
} else if (code > 1) {
- console.error(chalk.red(`Worker exited with exit code: ${code.toString()}`));
+ console.error(chalk.red(`Worker exited with exit code: ${code.toString()}`))
}
-};
+}
export const defaultErrorHandler = (error: Error): void => {
- console.error(chalk.red('Worker errored: '), error);
-};
+ console.error(chalk.red('Worker errored: '), error)
+}
export const randomizeDelay = (delay: number): number => {
- const random = secureRandom();
- const sign = random < 0.5 ? -1 : 1;
- const randomSum = delay * 0.2 * random; // 0-20% of the delay
- return delay + sign * randomSum;
-};
+ const random = secureRandom()
+ const sign = random < 0.5 ? -1 : 1
+ const randomSum = delay * 0.2 * random // 0-20% of the delay
+ return delay + sign * randomSum
+}
/**
* Generates a cryptographically secure random number in the [0,1[ range
* @internal
*/
const secureRandom = (): number => {
- return getRandomValues(new Uint32Array(1))[0] / 0x100000000;
-};
+ return getRandomValues(new Uint32Array(1))[0] / 0x100000000
+}
-export type { WorkerAbstract } from './WorkerAbstract.js';
+export type { WorkerAbstract } from './WorkerAbstract.js'
export {
DEFAULT_ELEMENT_START_DELAY,
DEFAULT_POOL_MAX_SIZE,
DEFAULT_POOL_MIN_SIZE,
- DEFAULT_WORKER_START_DELAY,
-} from './WorkerConstants.js';
-export { WorkerFactory } from './WorkerFactory.js';
+ DEFAULT_WORKER_START_DELAY
+} from './WorkerConstants.js'
+export { WorkerFactory } from './WorkerFactory.js'
export {
type WorkerData,
WorkerEvents,
type WorkerMessage,
WorkerMessageEvents,
- WorkerProcessType,
-} from './WorkerTypes.js';
+ WorkerProcessType
+} from './WorkerTypes.js'
-import { describe, it } from 'node:test';
+import { describe, it } from 'node:test'
-import { expect } from 'expect';
+import { expect } from 'expect'
-import { CircularArray, DEFAULT_CIRCULAR_ARRAY_SIZE } from '../../src/utils/CircularArray.js';
+import { CircularArray, DEFAULT_CIRCULAR_ARRAY_SIZE } from '../../src/utils/CircularArray.js'
await describe('CircularArray test suite', async () => {
await it('Verify that circular array can be instantiated', () => {
- const circularArray = new CircularArray();
- expect(circularArray).toBeInstanceOf(CircularArray);
- });
+ const circularArray = new CircularArray()
+ expect(circularArray).toBeInstanceOf(CircularArray)
+ })
await it('Verify circular array default size at instance creation', () => {
- const circularArray = new CircularArray();
- expect(circularArray.size).toBe(DEFAULT_CIRCULAR_ARRAY_SIZE);
- });
+ const circularArray = new CircularArray()
+ expect(circularArray.size).toBe(DEFAULT_CIRCULAR_ARRAY_SIZE)
+ })
await it('Verify that circular array size can be set at instance creation', () => {
- const circularArray = new CircularArray(1000);
- expect(circularArray.size).toBe(1000);
- });
+ const circularArray = new CircularArray(1000)
+ expect(circularArray.size).toBe(1000)
+ })
await it('Verify that circular array size and items can be set at instance creation', () => {
- let circularArray = new CircularArray(1000, 1, 2, 3, 4, 5);
- expect(circularArray.size).toBe(1000);
- expect(circularArray.length).toBe(5);
- circularArray = new CircularArray(4, 1, 2, 3, 4, 5);
- expect(circularArray.size).toBe(4);
- expect(circularArray.length).toBe(4);
- });
+ let circularArray = new CircularArray(1000, 1, 2, 3, 4, 5)
+ expect(circularArray.size).toBe(1000)
+ expect(circularArray.length).toBe(5)
+ circularArray = new CircularArray(4, 1, 2, 3, 4, 5)
+ expect(circularArray.size).toBe(4)
+ expect(circularArray.length).toBe(4)
+ })
await it('Verify that circular array size is valid at instance creation', () => {
expect(() => new CircularArray(0.25)).toThrow(
- new TypeError('Invalid circular array size: 0.25 is not a safe integer'),
- );
+ new TypeError('Invalid circular array size: 0.25 is not a safe integer')
+ )
expect(() => new CircularArray(-1)).toThrow(
- new RangeError('Invalid circular array size: -1 < 0'),
- );
+ new RangeError('Invalid circular array size: -1 < 0')
+ )
expect(() => new CircularArray(Number.MAX_SAFE_INTEGER + 1)).toThrow(
new TypeError(
- `Invalid circular array size: ${Number.MAX_SAFE_INTEGER + 1} is not a safe integer`,
- ),
- );
- });
+ `Invalid circular array size: ${Number.MAX_SAFE_INTEGER + 1} is not a safe integer`
+ )
+ )
+ })
await it('Verify that circular array empty works as intended', () => {
- const circularArray = new CircularArray();
- expect(circularArray.empty()).toBe(true);
- });
+ const circularArray = new CircularArray()
+ expect(circularArray.empty()).toBe(true)
+ })
await it('Verify that circular array full works as intended', () => {
- const circularArray = new CircularArray(5, 1, 2, 3, 4, 5);
- expect(circularArray.full()).toBe(true);
- });
+ const circularArray = new CircularArray(5, 1, 2, 3, 4, 5)
+ expect(circularArray.full()).toBe(true)
+ })
await it('Verify that circular array push works as intended', () => {
- let circularArray = new CircularArray(4);
- let arrayLength = circularArray.push(1, 2, 3, 4, 5);
- expect(arrayLength).toBe(circularArray.size);
- expect(circularArray.length).toBe(circularArray.size);
- expect(circularArray).toStrictEqual(new CircularArray(4, 2, 3, 4, 5));
- arrayLength = circularArray.push(6, 7);
- expect(arrayLength).toBe(circularArray.size);
- expect(circularArray.length).toBe(circularArray.size);
- expect(circularArray).toStrictEqual(new CircularArray(4, 4, 5, 6, 7));
- circularArray = new CircularArray(100);
- arrayLength = circularArray.push(1, 2, 3, 4, 5);
- expect(arrayLength).toBe(5);
- expect(circularArray.size).toBe(100);
- expect(circularArray.length).toBe(5);
- expect(circularArray).toStrictEqual(new CircularArray(100, 1, 2, 3, 4, 5));
- });
+ let circularArray = new CircularArray(4)
+ let arrayLength = circularArray.push(1, 2, 3, 4, 5)
+ expect(arrayLength).toBe(circularArray.size)
+ expect(circularArray.length).toBe(circularArray.size)
+ expect(circularArray).toStrictEqual(new CircularArray(4, 2, 3, 4, 5))
+ arrayLength = circularArray.push(6, 7)
+ expect(arrayLength).toBe(circularArray.size)
+ expect(circularArray.length).toBe(circularArray.size)
+ expect(circularArray).toStrictEqual(new CircularArray(4, 4, 5, 6, 7))
+ circularArray = new CircularArray(100)
+ arrayLength = circularArray.push(1, 2, 3, 4, 5)
+ expect(arrayLength).toBe(5)
+ expect(circularArray.size).toBe(100)
+ expect(circularArray.length).toBe(5)
+ expect(circularArray).toStrictEqual(new CircularArray(100, 1, 2, 3, 4, 5))
+ })
await it('Verify that circular array splice works as intended', () => {
- let circularArray = new CircularArray(1000, 1, 2, 3, 4, 5);
- let deletedItems = circularArray.splice(2);
- expect(deletedItems).toStrictEqual(new CircularArray(3, 3, 4, 5));
- expect(circularArray.length).toBe(2);
- expect(circularArray).toStrictEqual(new CircularArray(1000, 1, 2));
- circularArray = new CircularArray(1000, 1, 2, 3, 4, 5);
- deletedItems = circularArray.splice(2, 1);
- expect(deletedItems).toStrictEqual(new CircularArray(1, 3));
- expect(circularArray.length).toBe(4);
- expect(circularArray).toStrictEqual(new CircularArray(1000, 1, 2, 4, 5));
- circularArray = new CircularArray(4, 1, 2, 3, 4);
- deletedItems = circularArray.splice(2, 1, 5, 6);
- expect(deletedItems).toStrictEqual(new CircularArray(2, 3, 1));
- expect(circularArray.length).toBe(4);
- expect(circularArray).toStrictEqual(new CircularArray(4, 2, 5, 6, 4));
- });
+ let circularArray = new CircularArray(1000, 1, 2, 3, 4, 5)
+ let deletedItems = circularArray.splice(2)
+ expect(deletedItems).toStrictEqual(new CircularArray(3, 3, 4, 5))
+ expect(circularArray.length).toBe(2)
+ expect(circularArray).toStrictEqual(new CircularArray(1000, 1, 2))
+ circularArray = new CircularArray(1000, 1, 2, 3, 4, 5)
+ deletedItems = circularArray.splice(2, 1)
+ expect(deletedItems).toStrictEqual(new CircularArray(1, 3))
+ expect(circularArray.length).toBe(4)
+ expect(circularArray).toStrictEqual(new CircularArray(1000, 1, 2, 4, 5))
+ circularArray = new CircularArray(4, 1, 2, 3, 4)
+ deletedItems = circularArray.splice(2, 1, 5, 6)
+ expect(deletedItems).toStrictEqual(new CircularArray(2, 3, 1))
+ expect(circularArray.length).toBe(4)
+ expect(circularArray).toStrictEqual(new CircularArray(4, 2, 5, 6, 4))
+ })
await it('Verify that circular array concat works as intended', () => {
- let circularArray = new CircularArray(5, 1, 2, 3, 4, 5);
- circularArray = circularArray.concat(6, 7);
- expect(circularArray.length).toBe(5);
- expect(circularArray).toStrictEqual(new CircularArray(5, 3, 4, 5, 6, 7));
- circularArray = new CircularArray(1);
- circularArray = circularArray.concat(6, 7);
- expect(circularArray.length).toBe(1);
- expect(circularArray).toStrictEqual(new CircularArray(1, 7));
- });
+ let circularArray = new CircularArray(5, 1, 2, 3, 4, 5)
+ circularArray = circularArray.concat(6, 7)
+ expect(circularArray.length).toBe(5)
+ expect(circularArray).toStrictEqual(new CircularArray(5, 3, 4, 5, 6, 7))
+ circularArray = new CircularArray(1)
+ circularArray = circularArray.concat(6, 7)
+ expect(circularArray.length).toBe(1)
+ expect(circularArray).toStrictEqual(new CircularArray(1, 7))
+ })
await it('Verify that circular array unshift works as intended', () => {
- let circularArray = new CircularArray(5, 1, 2, 3, 4, 5);
- let arrayLength = circularArray.unshift(6, 7);
- expect(arrayLength).toBe(5);
- expect(circularArray.length).toBe(5);
- expect(circularArray).toStrictEqual(new CircularArray(5, 6, 7, 1, 2, 3));
- circularArray = new CircularArray(1);
- arrayLength = circularArray.unshift(6, 7);
- expect(arrayLength).toBe(1);
- expect(circularArray.length).toBe(1);
- expect(circularArray).toStrictEqual(new CircularArray(1, 6));
- });
+ let circularArray = new CircularArray(5, 1, 2, 3, 4, 5)
+ let arrayLength = circularArray.unshift(6, 7)
+ expect(arrayLength).toBe(5)
+ expect(circularArray.length).toBe(5)
+ expect(circularArray).toStrictEqual(new CircularArray(5, 6, 7, 1, 2, 3))
+ circularArray = new CircularArray(1)
+ arrayLength = circularArray.unshift(6, 7)
+ expect(arrayLength).toBe(1)
+ expect(circularArray.length).toBe(1)
+ expect(circularArray).toStrictEqual(new CircularArray(1, 6))
+ })
await it('Verify that circular array resize works as intended', () => {
- expect(() => new CircularArray().resize(0.25)).toThrow(
- new TypeError('Invalid circular array size: 0.25 is not a safe integer'),
- );
- expect(() => new CircularArray().resize(-1)).toThrow(
- new RangeError('Invalid circular array size: -1 < 0'),
- );
- expect(() => new CircularArray().resize(Number.MAX_SAFE_INTEGER + 1)).toThrow(
+ expect(() => {
+ new CircularArray().resize(0.25)
+ }).toThrow(new TypeError('Invalid circular array size: 0.25 is not a safe integer'))
+ expect(() => {
+ new CircularArray().resize(-1)
+ }).toThrow(new RangeError('Invalid circular array size: -1 < 0'))
+ expect(() => {
+ new CircularArray().resize(Number.MAX_SAFE_INTEGER + 1)
+ }).toThrow(
new TypeError(
- `Invalid circular array size: ${Number.MAX_SAFE_INTEGER + 1} is not a safe integer`,
- ),
- );
- let circularArray = new CircularArray(5, 1, 2, 3, 4, 5);
- circularArray.resize(0);
- expect(circularArray.size).toBe(0);
- expect(circularArray).toStrictEqual(new CircularArray(0));
- circularArray = new CircularArray(5, 1, 2, 3, 4, 5);
- circularArray.resize(1);
- expect(circularArray.size).toBe(1);
- expect(circularArray).toStrictEqual(new CircularArray(1, 1));
- circularArray = new CircularArray(5, 1, 2, 3, 4, 5);
- circularArray.resize(3);
- expect(circularArray.size).toBe(3);
- expect(circularArray).toStrictEqual(new CircularArray(3, 1, 2, 3));
- circularArray = new CircularArray(5, 1, 2, 3, 4, 5);
- circularArray.resize(8);
- expect(circularArray.size).toBe(8);
- expect(circularArray).toStrictEqual(new CircularArray(8, 1, 2, 3, 4, 5));
- });
-});
+ `Invalid circular array size: ${Number.MAX_SAFE_INTEGER + 1} is not a safe integer`
+ )
+ )
+ let circularArray = new CircularArray(5, 1, 2, 3, 4, 5)
+ circularArray.resize(0)
+ expect(circularArray.size).toBe(0)
+ expect(circularArray).toStrictEqual(new CircularArray(0))
+ circularArray = new CircularArray(5, 1, 2, 3, 4, 5)
+ circularArray.resize(1)
+ expect(circularArray.size).toBe(1)
+ expect(circularArray).toStrictEqual(new CircularArray(1, 1))
+ circularArray = new CircularArray(5, 1, 2, 3, 4, 5)
+ circularArray.resize(3)
+ expect(circularArray.size).toBe(3)
+ expect(circularArray).toStrictEqual(new CircularArray(3, 1, 2, 3))
+ circularArray = new CircularArray(5, 1, 2, 3, 4, 5)
+ circularArray.resize(8)
+ expect(circularArray.size).toBe(8)
+ expect(circularArray).toStrictEqual(new CircularArray(8, 1, 2, 3, 4, 5))
+ })
+})
-import { describe, it } from 'node:test';
+import { describe, it } from 'node:test'
-import { expect } from 'expect';
+import { expect } from 'expect'
-import { ACElectricUtils, DCElectricUtils } from '../../src/utils/ElectricUtils.js';
+import { ACElectricUtils, DCElectricUtils } from '../../src/utils/ElectricUtils.js'
await describe('ElectricUtils test suite', async () => {
await it('Verify DCElectricUtils.power()', () => {
- expect(DCElectricUtils.power(230, 1)).toBe(230);
- });
+ expect(DCElectricUtils.power(230, 1)).toBe(230)
+ })
await it('Verify DCElectricUtils.amperage()', () => {
- expect(DCElectricUtils.amperage(1, 230)).toBe(0);
- });
+ expect(DCElectricUtils.amperage(1, 230)).toBe(0)
+ })
await it('Verify ACElectricUtils.powerTotal()', () => {
- expect(ACElectricUtils.powerTotal(3, 230, 1)).toBe(690);
- });
+ expect(ACElectricUtils.powerTotal(3, 230, 1)).toBe(690)
+ })
await it('Verify ACElectricUtils.powerPerPhase()', () => {
- expect(ACElectricUtils.powerPerPhase(230, 1)).toBe(230);
- });
+ expect(ACElectricUtils.powerPerPhase(230, 1)).toBe(230)
+ })
await it('Verify ACElectricUtils.amperageTotal()', () => {
- expect(ACElectricUtils.amperageTotal(3, 1)).toBe(3);
- });
+ expect(ACElectricUtils.amperageTotal(3, 1)).toBe(3)
+ })
await it('Verify ACElectricUtils.amperageTotalFromPower()', () => {
- expect(ACElectricUtils.amperageTotalFromPower(690, 230)).toBe(3);
- });
+ expect(ACElectricUtils.amperageTotalFromPower(690, 230)).toBe(3)
+ })
await it('Verify ACElectricUtils.amperagePerPhaseFromPower()', () => {
- expect(ACElectricUtils.amperagePerPhaseFromPower(3, 690, 230)).toBe(1);
- });
-});
+ expect(ACElectricUtils.amperagePerPhaseFromPower(3, 690, 230)).toBe(1)
+ })
+})
-import { describe, it } from 'node:test';
+import { describe, it } from 'node:test'
-import { expect } from 'expect';
+import { expect } from 'expect'
-import { average, median, nthPercentile, stdDeviation } from '../../src/utils/StatisticUtils.js';
+import { average, median, nthPercentile, stdDeviation } from '../../src/utils/StatisticUtils.js'
await describe('StatisticUtils test suite', async () => {
await it('Verify average()', () => {
- expect(average([])).toBe(0);
- expect(average([0.08])).toBe(0.08);
- expect(average([0.25, 4.75, 3.05, 6.04, 1.01, 2.02, 5.03])).toBe(3.1642857142857146);
- expect(average([0.25, 4.75, 3.05, 6.04, 1.01, 2.02])).toBe(2.8533333333333335);
- });
+ expect(average([])).toBe(0)
+ expect(average([0.08])).toBe(0.08)
+ expect(average([0.25, 4.75, 3.05, 6.04, 1.01, 2.02, 5.03])).toBe(3.1642857142857146)
+ expect(average([0.25, 4.75, 3.05, 6.04, 1.01, 2.02])).toBe(2.8533333333333335)
+ })
await it('Verify median()', () => {
- expect(median([])).toBe(0);
- expect(median([0.08])).toBe(0.08);
- expect(median([0.25, 4.75, 3.05, 6.04, 1.01, 2.02, 5.03])).toBe(3.05);
- expect(median([0.25, 4.75, 3.05, 6.04, 1.01, 2.02])).toBe(2.535);
- });
+ expect(median([])).toBe(0)
+ expect(median([0.08])).toBe(0.08)
+ expect(median([0.25, 4.75, 3.05, 6.04, 1.01, 2.02, 5.03])).toBe(3.05)
+ expect(median([0.25, 4.75, 3.05, 6.04, 1.01, 2.02])).toBe(2.535)
+ })
await it('Verify nthPercentile()', () => {
- expect(nthPercentile([], 25)).toBe(0);
- expect(nthPercentile([0.08], 50)).toBe(0.08);
- const array0 = [0.25, 4.75, 3.05, 6.04, 1.01, 2.02, 5.03];
- expect(nthPercentile(array0, 0)).toBe(0.25);
- expect(nthPercentile(array0, 50)).toBe(3.05);
- expect(nthPercentile(array0, 80)).toBe(4.974);
- expect(nthPercentile(array0, 85)).toBe(5.131);
- expect(nthPercentile(array0, 90)).toBe(5.434);
- expect(nthPercentile(array0, 95)).toBe(5.736999999999999);
- expect(nthPercentile(array0, 100)).toBe(6.04);
- });
+ expect(nthPercentile([], 25)).toBe(0)
+ expect(nthPercentile([0.08], 50)).toBe(0.08)
+ const array0 = [0.25, 4.75, 3.05, 6.04, 1.01, 2.02, 5.03]
+ expect(nthPercentile(array0, 0)).toBe(0.25)
+ expect(nthPercentile(array0, 50)).toBe(3.05)
+ expect(nthPercentile(array0, 80)).toBe(4.974)
+ expect(nthPercentile(array0, 85)).toBe(5.131)
+ expect(nthPercentile(array0, 90)).toBe(5.434)
+ expect(nthPercentile(array0, 95)).toBe(5.736999999999999)
+ expect(nthPercentile(array0, 100)).toBe(6.04)
+ })
await it('Verify stdDeviation()', () => {
- expect(stdDeviation([0.25, 4.75, 3.05, 6.04, 1.01, 2.02, 5.03])).toBe(2.1879050645374383);
- });
-});
+ expect(stdDeviation([0.25, 4.75, 3.05, 6.04, 1.01, 2.02, 5.03])).toBe(2.1879050645374383)
+ })
+})
-import { describe, it } from 'node:test';
+import { describe, it } from 'node:test'
-import { hoursToMilliseconds, hoursToSeconds } from 'date-fns';
-import { expect } from 'expect';
+import { hoursToMilliseconds, hoursToSeconds } from 'date-fns'
+import { expect } from 'expect'
-import { Constants } from '../../src/utils/Constants.js';
+import { Constants } from '../../src/utils/Constants.js'
import {
cloneObject,
convertToBoolean,
roundTo,
secureRandom,
sleep,
- validateUUID,
-} from '../../src/utils/Utils.js';
+ validateUUID
+} from '../../src/utils/Utils.js'
await describe('Utils test suite', async () => {
await it('Verify generateUUID()/validateUUID()', () => {
- const uuid = generateUUID();
- expect(uuid).toBeDefined();
- expect(uuid.length).toEqual(36);
- expect(validateUUID(uuid)).toBe(true);
- expect(validateUUID('abcdef00-0000-4000-0000-000000000000')).toBe(true);
- expect(validateUUID('')).toBe(false);
+ const uuid = generateUUID()
+ expect(uuid).toBeDefined()
+ expect(uuid.length).toEqual(36)
+ expect(validateUUID(uuid)).toBe(true)
+ expect(validateUUID('abcdef00-0000-4000-0000-000000000000')).toBe(true)
+ expect(validateUUID('')).toBe(false)
// Shall invalidate Nil UUID
- expect(validateUUID('00000000-0000-0000-0000-000000000000')).toBe(false);
- expect(validateUUID('987FBC9-4BED-3078-CF07A-9141BA07C9F3')).toBe(false);
- });
+ expect(validateUUID('00000000-0000-0000-0000-000000000000')).toBe(false)
+ expect(validateUUID('987FBC9-4BED-3078-CF07A-9141BA07C9F3')).toBe(false)
+ })
await it('Verify sleep()', async () => {
- const start = performance.now();
- await sleep(1000);
- const stop = performance.now();
- expect(stop - start).toBeGreaterThanOrEqual(1000);
- });
+ const start = performance.now()
+ await sleep(1000)
+ const stop = performance.now()
+ expect(stop - start).toBeGreaterThanOrEqual(1000)
+ })
await it('Verify formatDurationMilliSeconds()', () => {
- expect(formatDurationMilliSeconds(0)).toBe('0 seconds');
- expect(formatDurationMilliSeconds(900)).toBe('0 seconds');
- expect(formatDurationMilliSeconds(1000)).toBe('1 second');
- expect(formatDurationMilliSeconds(hoursToMilliseconds(4380))).toBe('182 days 12 hours');
- });
+ expect(formatDurationMilliSeconds(0)).toBe('0 seconds')
+ expect(formatDurationMilliSeconds(900)).toBe('0 seconds')
+ expect(formatDurationMilliSeconds(1000)).toBe('1 second')
+ expect(formatDurationMilliSeconds(hoursToMilliseconds(4380))).toBe('182 days 12 hours')
+ })
await it('Verify formatDurationSeconds()', () => {
- expect(formatDurationSeconds(0)).toBe('0 seconds');
- expect(formatDurationSeconds(0.9)).toBe('0 seconds');
- expect(formatDurationSeconds(1)).toBe('1 second');
- expect(formatDurationSeconds(hoursToSeconds(4380))).toBe('182 days 12 hours');
- });
+ expect(formatDurationSeconds(0)).toBe('0 seconds')
+ expect(formatDurationSeconds(0.9)).toBe('0 seconds')
+ expect(formatDurationSeconds(1)).toBe('1 second')
+ expect(formatDurationSeconds(hoursToSeconds(4380))).toBe('182 days 12 hours')
+ })
await it('Verify isValidTime()', () => {
- expect(isValidTime(undefined)).toBe(false);
- expect(isValidTime(null)).toBe(false);
- expect(isValidTime('')).toBe(false);
- expect(isValidTime({})).toBe(false);
- expect(isValidTime([])).toBe(false);
- expect(isValidTime(new Map())).toBe(false);
- expect(isValidTime(new Set())).toBe(false);
- expect(isValidTime(new WeakMap())).toBe(false);
- expect(isValidTime(new WeakSet())).toBe(false);
- expect(isValidTime(-1)).toBe(true);
- expect(isValidTime(0)).toBe(true);
- expect(isValidTime(1)).toBe(true);
- expect(isValidTime(-0.5)).toBe(true);
- expect(isValidTime(0.5)).toBe(true);
- expect(isValidTime(new Date())).toBe(true);
- });
+ expect(isValidTime(undefined)).toBe(false)
+ expect(isValidTime(null)).toBe(false)
+ expect(isValidTime('')).toBe(false)
+ expect(isValidTime({})).toBe(false)
+ expect(isValidTime([])).toBe(false)
+ expect(isValidTime(new Map())).toBe(false)
+ expect(isValidTime(new Set())).toBe(false)
+ expect(isValidTime(new WeakMap())).toBe(false)
+ expect(isValidTime(new WeakSet())).toBe(false)
+ expect(isValidTime(-1)).toBe(true)
+ expect(isValidTime(0)).toBe(true)
+ expect(isValidTime(1)).toBe(true)
+ expect(isValidTime(-0.5)).toBe(true)
+ expect(isValidTime(0.5)).toBe(true)
+ expect(isValidTime(new Date())).toBe(true)
+ })
await it('Verify convertToDate()', () => {
- expect(convertToDate(undefined)).toBe(undefined);
- expect(convertToDate(null)).toBe(null);
- expect(() => convertToDate('')).toThrow(new Error("Cannot convert to date: ''"));
- expect(() => convertToDate('00:70:61')).toThrow(
- new Error("Cannot convert to date: '00:70:61'"),
- );
- expect(convertToDate(0)).toStrictEqual(new Date('1970-01-01T00:00:00.000Z'));
- expect(convertToDate(-1)).toStrictEqual(new Date('1969-12-31T23:59:59.999Z'));
- const dateStr = '2020-01-01T00:00:00.000Z';
- let date = convertToDate(dateStr);
- expect(date).toBeInstanceOf(Date);
- expect(date).toStrictEqual(new Date(dateStr));
- date = convertToDate(new Date(dateStr));
- expect(date).toBeInstanceOf(Date);
- expect(date).toStrictEqual(new Date(dateStr));
- });
+ expect(convertToDate(undefined)).toBe(undefined)
+ expect(convertToDate(null)).toBe(null)
+ expect(() => convertToDate('')).toThrow(new Error("Cannot convert to date: ''"))
+ expect(() => convertToDate('00:70:61')).toThrow(new Error("Cannot convert to date: '00:70:61'"))
+ expect(convertToDate(0)).toStrictEqual(new Date('1970-01-01T00:00:00.000Z'))
+ expect(convertToDate(-1)).toStrictEqual(new Date('1969-12-31T23:59:59.999Z'))
+ const dateStr = '2020-01-01T00:00:00.000Z'
+ let date = convertToDate(dateStr)
+ expect(date).toBeInstanceOf(Date)
+ expect(date).toStrictEqual(new Date(dateStr))
+ date = convertToDate(new Date(dateStr))
+ expect(date).toBeInstanceOf(Date)
+ expect(date).toStrictEqual(new Date(dateStr))
+ })
await it('Verify convertToInt()', () => {
- expect(convertToInt(undefined)).toBe(0);
- expect(convertToInt(null)).toBe(0);
- expect(convertToInt(0)).toBe(0);
- const randomInteger = getRandomInteger();
- expect(convertToInt(randomInteger)).toEqual(randomInteger);
- expect(convertToInt('-1')).toBe(-1);
- expect(convertToInt('1')).toBe(1);
- expect(convertToInt('1.1')).toBe(1);
- expect(convertToInt('1.9')).toBe(1);
- expect(convertToInt('1.999')).toBe(1);
- expect(convertToInt(-1)).toBe(-1);
- expect(convertToInt(1)).toBe(1);
- expect(convertToInt(1.1)).toBe(1);
- expect(convertToInt(1.9)).toBe(1);
- expect(convertToInt(1.999)).toBe(1);
+ expect(convertToInt(undefined)).toBe(0)
+ expect(convertToInt(null)).toBe(0)
+ expect(convertToInt(0)).toBe(0)
+ const randomInteger = getRandomInteger()
+ expect(convertToInt(randomInteger)).toEqual(randomInteger)
+ expect(convertToInt('-1')).toBe(-1)
+ expect(convertToInt('1')).toBe(1)
+ expect(convertToInt('1.1')).toBe(1)
+ expect(convertToInt('1.9')).toBe(1)
+ expect(convertToInt('1.999')).toBe(1)
+ expect(convertToInt(-1)).toBe(-1)
+ expect(convertToInt(1)).toBe(1)
+ expect(convertToInt(1.1)).toBe(1)
+ expect(convertToInt(1.9)).toBe(1)
+ expect(convertToInt(1.999)).toBe(1)
expect(() => {
- convertToInt('NaN');
- }).toThrow("Cannot convert to integer: 'NaN'");
- });
+ convertToInt('NaN')
+ }).toThrow("Cannot convert to integer: 'NaN'")
+ })
await it('Verify convertToFloat()', () => {
- expect(convertToFloat(undefined)).toBe(0);
- expect(convertToFloat(null)).toBe(0);
- expect(convertToFloat(0)).toBe(0);
- const randomFloat = getRandomFloat();
- expect(convertToFloat(randomFloat)).toEqual(randomFloat);
- expect(convertToFloat('-1')).toBe(-1);
- expect(convertToFloat('1')).toBe(1);
- expect(convertToFloat('1.1')).toBe(1.1);
- expect(convertToFloat('1.9')).toBe(1.9);
- expect(convertToFloat('1.999')).toBe(1.999);
- expect(convertToFloat(-1)).toBe(-1);
- expect(convertToFloat(1)).toBe(1);
- expect(convertToFloat(1.1)).toBe(1.1);
- expect(convertToFloat(1.9)).toBe(1.9);
- expect(convertToFloat(1.999)).toBe(1.999);
+ expect(convertToFloat(undefined)).toBe(0)
+ expect(convertToFloat(null)).toBe(0)
+ expect(convertToFloat(0)).toBe(0)
+ const randomFloat = getRandomFloat()
+ expect(convertToFloat(randomFloat)).toEqual(randomFloat)
+ expect(convertToFloat('-1')).toBe(-1)
+ expect(convertToFloat('1')).toBe(1)
+ expect(convertToFloat('1.1')).toBe(1.1)
+ expect(convertToFloat('1.9')).toBe(1.9)
+ expect(convertToFloat('1.999')).toBe(1.999)
+ expect(convertToFloat(-1)).toBe(-1)
+ expect(convertToFloat(1)).toBe(1)
+ expect(convertToFloat(1.1)).toBe(1.1)
+ expect(convertToFloat(1.9)).toBe(1.9)
+ expect(convertToFloat(1.999)).toBe(1.999)
expect(() => {
- convertToFloat('NaN');
- }).toThrow("Cannot convert to float: 'NaN'");
- });
+ convertToFloat('NaN')
+ }).toThrow("Cannot convert to float: 'NaN'")
+ })
await it('Verify convertToBoolean()', () => {
- expect(convertToBoolean(undefined)).toBe(false);
- expect(convertToBoolean(null)).toBe(false);
- expect(convertToBoolean('true')).toBe(true);
- expect(convertToBoolean('false')).toBe(false);
- expect(convertToBoolean('TRUE')).toBe(true);
- expect(convertToBoolean('FALSE')).toBe(false);
- expect(convertToBoolean('1')).toBe(true);
- expect(convertToBoolean('0')).toBe(false);
- expect(convertToBoolean(1)).toBe(true);
- expect(convertToBoolean(0)).toBe(false);
- expect(convertToBoolean(true)).toBe(true);
- expect(convertToBoolean(false)).toBe(false);
- expect(convertToBoolean('')).toBe(false);
- expect(convertToBoolean('NoNBoolean')).toBe(false);
- });
+ expect(convertToBoolean(undefined)).toBe(false)
+ expect(convertToBoolean(null)).toBe(false)
+ expect(convertToBoolean('true')).toBe(true)
+ expect(convertToBoolean('false')).toBe(false)
+ expect(convertToBoolean('TRUE')).toBe(true)
+ expect(convertToBoolean('FALSE')).toBe(false)
+ expect(convertToBoolean('1')).toBe(true)
+ expect(convertToBoolean('0')).toBe(false)
+ expect(convertToBoolean(1)).toBe(true)
+ expect(convertToBoolean(0)).toBe(false)
+ expect(convertToBoolean(true)).toBe(true)
+ expect(convertToBoolean(false)).toBe(false)
+ expect(convertToBoolean('')).toBe(false)
+ expect(convertToBoolean('NoNBoolean')).toBe(false)
+ })
await it('Verify secureRandom()', () => {
- const random = secureRandom();
- expect(typeof random === 'number').toBe(true);
- expect(random).toBeGreaterThanOrEqual(0);
- expect(random).toBeLessThan(1);
- });
+ const random = secureRandom()
+ expect(typeof random === 'number').toBe(true)
+ expect(random).toBeGreaterThanOrEqual(0)
+ expect(random).toBeLessThan(1)
+ })
await it('Verify getRandomInteger()', () => {
- let randomInteger = getRandomInteger();
- expect(Number.isSafeInteger(randomInteger)).toBe(true);
- expect(randomInteger).toBeGreaterThanOrEqual(0);
- expect(randomInteger).toBeLessThanOrEqual(Constants.MAX_RANDOM_INTEGER);
- expect(randomInteger).not.toEqual(getRandomInteger());
- randomInteger = getRandomInteger(0, -Constants.MAX_RANDOM_INTEGER);
- expect(randomInteger).toBeGreaterThanOrEqual(-Constants.MAX_RANDOM_INTEGER);
- expect(randomInteger).toBeLessThanOrEqual(0);
+ let randomInteger = getRandomInteger()
+ expect(Number.isSafeInteger(randomInteger)).toBe(true)
+ expect(randomInteger).toBeGreaterThanOrEqual(0)
+ expect(randomInteger).toBeLessThanOrEqual(Constants.MAX_RANDOM_INTEGER)
+ expect(randomInteger).not.toEqual(getRandomInteger())
+ randomInteger = getRandomInteger(0, -Constants.MAX_RANDOM_INTEGER)
+ expect(randomInteger).toBeGreaterThanOrEqual(-Constants.MAX_RANDOM_INTEGER)
+ expect(randomInteger).toBeLessThanOrEqual(0)
expect(() => getRandomInteger(0, 1)).toThrow(
- 'The value of "max" is out of range. It must be greater than the value of "min" (1). Received 1',
- );
+ 'The value of "max" is out of range. It must be greater than the value of "min" (1). Received 1'
+ )
expect(() => getRandomInteger(-1)).toThrow(
- 'The value of "max" is out of range. It must be greater than the value of "min" (0). Received 0',
- );
+ 'The value of "max" is out of range. It must be greater than the value of "min" (0). Received 0'
+ )
expect(() => getRandomInteger(Constants.MAX_RANDOM_INTEGER + 1)).toThrow(
`The value of "max" is out of range. It must be <= ${
Constants.MAX_RANDOM_INTEGER + 1
- }. Received 281_474_976_710_656`,
- );
- randomInteger = getRandomInteger(2, 1);
- expect(randomInteger).toBeGreaterThanOrEqual(1);
- expect(randomInteger).toBeLessThanOrEqual(2);
- const maximum = 2.2,
- minimum = 1.1;
- randomInteger = getRandomInteger(maximum, minimum);
- expect(randomInteger).toBeLessThanOrEqual(Math.floor(maximum));
- expect(randomInteger).toBeGreaterThanOrEqual(Math.ceil(minimum));
- });
+ }. Received 281_474_976_710_656`
+ )
+ randomInteger = getRandomInteger(2, 1)
+ expect(randomInteger).toBeGreaterThanOrEqual(1)
+ expect(randomInteger).toBeLessThanOrEqual(2)
+ const maximum = 2.2
+ const minimum = 1.1
+ randomInteger = getRandomInteger(maximum, minimum)
+ expect(randomInteger).toBeLessThanOrEqual(Math.floor(maximum))
+ expect(randomInteger).toBeGreaterThanOrEqual(Math.ceil(minimum))
+ })
await it('Verify roundTo()', () => {
- expect(roundTo(0, 2)).toBe(0);
- expect(roundTo(0.5, 0)).toBe(1);
- expect(roundTo(0.5, 2)).toBe(0.5);
- expect(roundTo(-0.5, 0)).toBe(-1);
- expect(roundTo(-0.5, 2)).toBe(-0.5);
- expect(roundTo(1.005, 0)).toBe(1);
- expect(roundTo(1.005, 2)).toBe(1.01);
- expect(roundTo(2.175, 2)).toBe(2.18);
- expect(roundTo(5.015, 2)).toBe(5.02);
- expect(roundTo(-1.005, 2)).toBe(-1.01);
- expect(roundTo(-2.175, 2)).toBe(-2.18);
- expect(roundTo(-5.015, 2)).toBe(-5.02);
- });
+ expect(roundTo(0, 2)).toBe(0)
+ expect(roundTo(0.5, 0)).toBe(1)
+ expect(roundTo(0.5, 2)).toBe(0.5)
+ expect(roundTo(-0.5, 0)).toBe(-1)
+ expect(roundTo(-0.5, 2)).toBe(-0.5)
+ expect(roundTo(1.005, 0)).toBe(1)
+ expect(roundTo(1.005, 2)).toBe(1.01)
+ expect(roundTo(2.175, 2)).toBe(2.18)
+ expect(roundTo(5.015, 2)).toBe(5.02)
+ expect(roundTo(-1.005, 2)).toBe(-1.01)
+ expect(roundTo(-2.175, 2)).toBe(-2.18)
+ expect(roundTo(-5.015, 2)).toBe(-5.02)
+ })
await it('Verify getRandomFloat()', () => {
- let randomFloat = getRandomFloat();
- expect(typeof randomFloat === 'number').toBe(true);
- expect(randomFloat).toBeGreaterThanOrEqual(0);
- expect(randomFloat).toBeLessThanOrEqual(Number.MAX_VALUE);
- expect(randomFloat).not.toEqual(getRandomFloat());
- expect(() => getRandomFloat(0, 1)).toThrow(new RangeError('Invalid interval'));
+ let randomFloat = getRandomFloat()
+ expect(typeof randomFloat === 'number').toBe(true)
+ expect(randomFloat).toBeGreaterThanOrEqual(0)
+ expect(randomFloat).toBeLessThanOrEqual(Number.MAX_VALUE)
+ expect(randomFloat).not.toEqual(getRandomFloat())
+ expect(() => getRandomFloat(0, 1)).toThrow(new RangeError('Invalid interval'))
expect(() => getRandomFloat(Number.MAX_VALUE, -Number.MAX_VALUE)).toThrow(
- new RangeError('Invalid interval'),
- );
- randomFloat = getRandomFloat(0, -Number.MAX_VALUE);
- expect(randomFloat).toBeGreaterThanOrEqual(-Number.MAX_VALUE);
- expect(randomFloat).toBeLessThanOrEqual(0);
- });
+ new RangeError('Invalid interval')
+ )
+ randomFloat = getRandomFloat(0, -Number.MAX_VALUE)
+ expect(randomFloat).toBeGreaterThanOrEqual(-Number.MAX_VALUE)
+ expect(randomFloat).toBeLessThanOrEqual(0)
+ })
await it('Verify extractTimeSeriesValues()', () => {
- expect(extractTimeSeriesValues([])).toEqual([]);
- expect(extractTimeSeriesValues([{ timestamp: Date.now(), value: 1.1 }])).toEqual([1.1]);
+ expect(extractTimeSeriesValues([])).toEqual([])
+ expect(extractTimeSeriesValues([{ timestamp: Date.now(), value: 1.1 }])).toEqual([1.1])
expect(
extractTimeSeriesValues([
{ timestamp: Date.now(), value: 1.1 },
- { timestamp: Date.now(), value: 2.2 },
- ]),
- ).toEqual([1.1, 2.2]);
- });
+ { timestamp: Date.now(), value: 2.2 }
+ ])
+ ).toEqual([1.1, 2.2])
+ })
await it('Verify isObject()', () => {
- expect(isObject('test')).toBe(false);
- expect(isObject(undefined)).toBe(false);
- expect(isObject(null)).toBe(false);
- expect(isObject(0)).toBe(false);
- expect(isObject([])).toBe(false);
- expect(isObject([0, 1])).toBe(false);
- expect(isObject(['0', '1'])).toBe(false);
- expect(isObject({})).toBe(true);
- expect(isObject({ 1: 1 })).toBe(true);
- expect(isObject({ '1': '1' })).toBe(true);
- expect(isObject(new Map())).toBe(true);
- expect(isObject(new Set())).toBe(true);
- expect(isObject(new WeakMap())).toBe(true);
- expect(isObject(new WeakSet())).toBe(true);
- });
+ expect(isObject('test')).toBe(false)
+ expect(isObject(undefined)).toBe(false)
+ expect(isObject(null)).toBe(false)
+ expect(isObject(0)).toBe(false)
+ expect(isObject([])).toBe(false)
+ expect(isObject([0, 1])).toBe(false)
+ expect(isObject(['0', '1'])).toBe(false)
+ expect(isObject({})).toBe(true)
+ expect(isObject({ 1: 1 })).toBe(true)
+ expect(isObject({ 1: '1' })).toBe(true)
+ expect(isObject(new Map())).toBe(true)
+ expect(isObject(new Set())).toBe(true)
+ expect(isObject(new WeakMap())).toBe(true)
+ expect(isObject(new WeakSet())).toBe(true)
+ })
await it('Verify cloneObject()', () => {
- const obj = { 1: 1 };
- expect(cloneObject(obj)).toStrictEqual(obj);
- expect(cloneObject(obj) === obj).toBe(false);
- const nestedObj = { 1: obj, 2: obj };
- expect(cloneObject(nestedObj)).toStrictEqual(nestedObj);
- expect(cloneObject(nestedObj) === nestedObj).toBe(false);
- const array = [1, 2];
- expect(cloneObject(array)).toStrictEqual(array);
- expect(cloneObject(array) === array).toBe(false);
- const objArray = [obj, obj];
- expect(cloneObject(objArray)).toStrictEqual(objArray);
- expect(cloneObject(objArray) === objArray).toBe(false);
- const date = new Date();
- expect(cloneObject(date)).toStrictEqual(date);
- expect(cloneObject(date) === date).toBe(false);
- const map = new Map([['1', '2']]);
- expect(cloneObject(map)).toStrictEqual({});
- const set = new Set(['1']);
- expect(cloneObject(set)).toStrictEqual({});
+ const obj = { 1: 1 }
+ expect(cloneObject(obj)).toStrictEqual(obj)
+ expect(cloneObject(obj) === obj).toBe(false)
+ const nestedObj = { 1: obj, 2: obj }
+ expect(cloneObject(nestedObj)).toStrictEqual(nestedObj)
+ expect(cloneObject(nestedObj) === nestedObj).toBe(false)
+ const array = [1, 2]
+ expect(cloneObject(array)).toStrictEqual(array)
+ expect(cloneObject(array) === array).toBe(false)
+ const objArray = [obj, obj]
+ expect(cloneObject(objArray)).toStrictEqual(objArray)
+ expect(cloneObject(objArray) === objArray).toBe(false)
+ const date = new Date()
+ expect(cloneObject(date)).toStrictEqual(date)
+ expect(cloneObject(date) === date).toBe(false)
+ const map = new Map([['1', '2']])
+ expect(cloneObject(map)).toStrictEqual({})
+ const set = new Set(['1'])
+ expect(cloneObject(set)).toStrictEqual({})
// The URL object seems to have not enumerable properties
- const url = new URL('https://domain.tld');
- expect(cloneObject(url)).toStrictEqual({});
- const weakMap = new WeakMap([[{ 1: 1 }, { 2: 2 }]]);
- expect(cloneObject(weakMap)).toStrictEqual({});
- const weakSet = new WeakSet([{ 1: 1 }, { 2: 2 }]);
- expect(cloneObject(weakSet)).toStrictEqual({});
- });
+ const url = new URL('https://domain.tld')
+ expect(cloneObject(url)).toStrictEqual({})
+ const weakMap = new WeakMap([[{ 1: 1 }, { 2: 2 }]])
+ expect(cloneObject(weakMap)).toStrictEqual({})
+ const weakSet = new WeakSet([{ 1: 1 }, { 2: 2 }])
+ expect(cloneObject(weakSet)).toStrictEqual({})
+ })
await it('Verify hasOwnProp()', () => {
- expect(hasOwnProp('test', '')).toBe(false);
- expect(hasOwnProp(undefined, '')).toBe(false);
- expect(hasOwnProp(null, '')).toBe(false);
- expect(hasOwnProp([], '')).toBe(false);
- expect(hasOwnProp({}, '')).toBe(false);
- expect(hasOwnProp({ 1: 1 }, 1)).toBe(true);
- expect(hasOwnProp({ 1: 1 }, '1')).toBe(true);
- expect(hasOwnProp({ 1: 1 }, 2)).toBe(false);
- expect(hasOwnProp({ 1: 1 }, '2')).toBe(false);
- expect(hasOwnProp({ '1': '1' }, '1')).toBe(true);
- expect(hasOwnProp({ '1': '1' }, 1)).toBe(true);
- expect(hasOwnProp({ '1': '1' }, '2')).toBe(false);
- expect(hasOwnProp({ '1': '1' }, 2)).toBe(false);
- });
+ expect(hasOwnProp('test', '')).toBe(false)
+ expect(hasOwnProp(undefined, '')).toBe(false)
+ expect(hasOwnProp(null, '')).toBe(false)
+ expect(hasOwnProp([], '')).toBe(false)
+ expect(hasOwnProp({}, '')).toBe(false)
+ expect(hasOwnProp({ 1: 1 }, 1)).toBe(true)
+ expect(hasOwnProp({ 1: 1 }, '1')).toBe(true)
+ expect(hasOwnProp({ 1: 1 }, 2)).toBe(false)
+ expect(hasOwnProp({ 1: 1 }, '2')).toBe(false)
+ expect(hasOwnProp({ 1: '1' }, '1')).toBe(true)
+ expect(hasOwnProp({ 1: '1' }, 1)).toBe(true)
+ expect(hasOwnProp({ 1: '1' }, '2')).toBe(false)
+ expect(hasOwnProp({ 1: '1' }, 2)).toBe(false)
+ })
await it('Verify isIterable()', () => {
- expect(isIterable('')).toBe(true);
- expect(isIterable(' ')).toBe(true);
- expect(isIterable('test')).toBe(true);
- expect(isIterable(undefined)).toBe(false);
- expect(isIterable(null)).toBe(false);
- expect(isIterable(0)).toBe(false);
- expect(isIterable([0, 1])).toBe(true);
- expect(isIterable({ 1: 1 })).toBe(false);
- expect(isIterable(new Map())).toBe(true);
- expect(isIterable(new Set())).toBe(true);
- expect(isIterable(new WeakMap())).toBe(false);
- expect(isIterable(new WeakSet())).toBe(false);
- });
+ expect(isIterable('')).toBe(true)
+ expect(isIterable(' ')).toBe(true)
+ expect(isIterable('test')).toBe(true)
+ expect(isIterable(undefined)).toBe(false)
+ expect(isIterable(null)).toBe(false)
+ expect(isIterable(0)).toBe(false)
+ expect(isIterable([0, 1])).toBe(true)
+ expect(isIterable({ 1: 1 })).toBe(false)
+ expect(isIterable(new Map())).toBe(true)
+ expect(isIterable(new Set())).toBe(true)
+ expect(isIterable(new WeakMap())).toBe(false)
+ expect(isIterable(new WeakSet())).toBe(false)
+ })
await it('Verify isEmptyString()', () => {
- expect(isEmptyString('')).toBe(true);
- expect(isEmptyString(' ')).toBe(true);
- expect(isEmptyString(' ')).toBe(true);
- expect(isEmptyString('test')).toBe(false);
- expect(isEmptyString(' test')).toBe(false);
- expect(isEmptyString('test ')).toBe(false);
- expect(isEmptyString(undefined)).toBe(true);
- expect(isEmptyString(null)).toBe(true);
- expect(isEmptyString(0)).toBe(false);
- expect(isEmptyString({})).toBe(false);
- expect(isEmptyString([])).toBe(false);
- expect(isEmptyString(new Map())).toBe(false);
- expect(isEmptyString(new Set())).toBe(false);
- expect(isEmptyString(new WeakMap())).toBe(false);
- expect(isEmptyString(new WeakSet())).toBe(false);
- });
+ expect(isEmptyString('')).toBe(true)
+ expect(isEmptyString(' ')).toBe(true)
+ expect(isEmptyString(' ')).toBe(true)
+ expect(isEmptyString('test')).toBe(false)
+ expect(isEmptyString(' test')).toBe(false)
+ expect(isEmptyString('test ')).toBe(false)
+ expect(isEmptyString(undefined)).toBe(true)
+ expect(isEmptyString(null)).toBe(true)
+ expect(isEmptyString(0)).toBe(false)
+ expect(isEmptyString({})).toBe(false)
+ expect(isEmptyString([])).toBe(false)
+ expect(isEmptyString(new Map())).toBe(false)
+ expect(isEmptyString(new Set())).toBe(false)
+ expect(isEmptyString(new WeakMap())).toBe(false)
+ expect(isEmptyString(new WeakSet())).toBe(false)
+ })
await it('Verify isNotEmptyString()', () => {
- expect(isNotEmptyString('')).toBe(false);
- expect(isNotEmptyString(' ')).toBe(false);
- expect(isNotEmptyString(' ')).toBe(false);
- expect(isNotEmptyString('test')).toBe(true);
- expect(isNotEmptyString(' test')).toBe(true);
- expect(isNotEmptyString('test ')).toBe(true);
- expect(isNotEmptyString(undefined)).toBe(false);
- expect(isNotEmptyString(null)).toBe(false);
- expect(isNotEmptyString(0)).toBe(false);
- expect(isNotEmptyString({})).toBe(false);
- expect(isNotEmptyString([])).toBe(false);
- expect(isNotEmptyString(new Map())).toBe(false);
- expect(isNotEmptyString(new Set())).toBe(false);
- expect(isNotEmptyString(new WeakMap())).toBe(false);
- expect(isNotEmptyString(new WeakSet())).toBe(false);
- });
+ expect(isNotEmptyString('')).toBe(false)
+ expect(isNotEmptyString(' ')).toBe(false)
+ expect(isNotEmptyString(' ')).toBe(false)
+ expect(isNotEmptyString('test')).toBe(true)
+ expect(isNotEmptyString(' test')).toBe(true)
+ expect(isNotEmptyString('test ')).toBe(true)
+ expect(isNotEmptyString(undefined)).toBe(false)
+ expect(isNotEmptyString(null)).toBe(false)
+ expect(isNotEmptyString(0)).toBe(false)
+ expect(isNotEmptyString({})).toBe(false)
+ expect(isNotEmptyString([])).toBe(false)
+ expect(isNotEmptyString(new Map())).toBe(false)
+ expect(isNotEmptyString(new Set())).toBe(false)
+ expect(isNotEmptyString(new WeakMap())).toBe(false)
+ expect(isNotEmptyString(new WeakSet())).toBe(false)
+ })
await it('Verify isUndefined()', () => {
- expect(isUndefined(undefined)).toBe(true);
- expect(isUndefined(null)).toBe(false);
- expect(isUndefined('')).toBe(false);
- expect(isUndefined(0)).toBe(false);
- expect(isUndefined({})).toBe(false);
- expect(isUndefined([])).toBe(false);
- expect(isUndefined(new Map())).toBe(false);
- expect(isUndefined(new Set())).toBe(false);
- expect(isUndefined(new WeakMap())).toBe(false);
- expect(isUndefined(new WeakSet())).toBe(false);
- });
+ expect(isUndefined(undefined)).toBe(true)
+ expect(isUndefined(null)).toBe(false)
+ expect(isUndefined('')).toBe(false)
+ expect(isUndefined(0)).toBe(false)
+ expect(isUndefined({})).toBe(false)
+ expect(isUndefined([])).toBe(false)
+ expect(isUndefined(new Map())).toBe(false)
+ expect(isUndefined(new Set())).toBe(false)
+ expect(isUndefined(new WeakMap())).toBe(false)
+ expect(isUndefined(new WeakSet())).toBe(false)
+ })
await it('Verify isNullOrUndefined()', () => {
- expect(isNullOrUndefined(undefined)).toBe(true);
- expect(isNullOrUndefined(null)).toBe(true);
- expect(isNullOrUndefined('')).toBe(false);
- expect(isNullOrUndefined(0)).toBe(false);
- expect(isNullOrUndefined({})).toBe(false);
- expect(isNullOrUndefined([])).toBe(false);
- expect(isNullOrUndefined(new Map())).toBe(false);
- expect(isNullOrUndefined(new Set())).toBe(false);
- expect(isNullOrUndefined(new WeakMap())).toBe(false);
- expect(isNullOrUndefined(new WeakSet())).toBe(false);
- });
+ expect(isNullOrUndefined(undefined)).toBe(true)
+ expect(isNullOrUndefined(null)).toBe(true)
+ expect(isNullOrUndefined('')).toBe(false)
+ expect(isNullOrUndefined(0)).toBe(false)
+ expect(isNullOrUndefined({})).toBe(false)
+ expect(isNullOrUndefined([])).toBe(false)
+ expect(isNullOrUndefined(new Map())).toBe(false)
+ expect(isNullOrUndefined(new Set())).toBe(false)
+ expect(isNullOrUndefined(new WeakMap())).toBe(false)
+ expect(isNullOrUndefined(new WeakSet())).toBe(false)
+ })
await it('Verify isEmptyArray()', () => {
- expect(isEmptyArray([])).toBe(true);
- expect(isEmptyArray([1, 2])).toBe(false);
- expect(isEmptyArray(['1', '2'])).toBe(false);
- expect(isEmptyArray(undefined)).toBe(false);
- expect(isEmptyArray(null)).toBe(false);
- expect(isEmptyArray('')).toBe(false);
- expect(isEmptyArray('test')).toBe(false);
- expect(isEmptyArray(0)).toBe(false);
- expect(isEmptyArray({})).toBe(false);
- expect(isEmptyArray(new Map())).toBe(false);
- expect(isEmptyArray(new Set())).toBe(false);
- expect(isEmptyArray(new WeakMap())).toBe(false);
- expect(isEmptyArray(new WeakSet())).toBe(false);
- });
+ expect(isEmptyArray([])).toBe(true)
+ expect(isEmptyArray([1, 2])).toBe(false)
+ expect(isEmptyArray(['1', '2'])).toBe(false)
+ expect(isEmptyArray(undefined)).toBe(false)
+ expect(isEmptyArray(null)).toBe(false)
+ expect(isEmptyArray('')).toBe(false)
+ expect(isEmptyArray('test')).toBe(false)
+ expect(isEmptyArray(0)).toBe(false)
+ expect(isEmptyArray({})).toBe(false)
+ expect(isEmptyArray(new Map())).toBe(false)
+ expect(isEmptyArray(new Set())).toBe(false)
+ expect(isEmptyArray(new WeakMap())).toBe(false)
+ expect(isEmptyArray(new WeakSet())).toBe(false)
+ })
await it('Verify isNotEmptyArray()', () => {
- expect(isNotEmptyArray([])).toBe(false);
- expect(isNotEmptyArray([1, 2])).toBe(true);
- expect(isNotEmptyArray(['1', '2'])).toBe(true);
- expect(isNotEmptyArray(undefined)).toBe(false);
- expect(isNotEmptyArray(null)).toBe(false);
- expect(isNotEmptyArray('')).toBe(false);
- expect(isNotEmptyArray('test')).toBe(false);
- expect(isNotEmptyArray(0)).toBe(false);
- expect(isNotEmptyArray({})).toBe(false);
- expect(isNotEmptyArray(new Map())).toBe(false);
- expect(isNotEmptyArray(new Set())).toBe(false);
- expect(isNotEmptyArray(new WeakMap())).toBe(false);
- expect(isNotEmptyArray(new WeakSet())).toBe(false);
- });
+ expect(isNotEmptyArray([])).toBe(false)
+ expect(isNotEmptyArray([1, 2])).toBe(true)
+ expect(isNotEmptyArray(['1', '2'])).toBe(true)
+ expect(isNotEmptyArray(undefined)).toBe(false)
+ expect(isNotEmptyArray(null)).toBe(false)
+ expect(isNotEmptyArray('')).toBe(false)
+ expect(isNotEmptyArray('test')).toBe(false)
+ expect(isNotEmptyArray(0)).toBe(false)
+ expect(isNotEmptyArray({})).toBe(false)
+ expect(isNotEmptyArray(new Map())).toBe(false)
+ expect(isNotEmptyArray(new Set())).toBe(false)
+ expect(isNotEmptyArray(new WeakMap())).toBe(false)
+ expect(isNotEmptyArray(new WeakSet())).toBe(false)
+ })
await it('Verify isEmptyObject()', () => {
- expect(isEmptyObject({})).toBe(true);
- expect(isEmptyObject({ 1: 1, 2: 2 })).toBe(false);
- expect(isEmptyObject(new Map())).toBe(false);
- expect(isEmptyObject(new Set())).toBe(false);
- expect(isEmptyObject(new WeakMap())).toBe(false);
- expect(isEmptyObject(new WeakSet())).toBe(false);
- });
+ expect(isEmptyObject({})).toBe(true)
+ expect(isEmptyObject({ 1: 1, 2: 2 })).toBe(false)
+ expect(isEmptyObject(new Map())).toBe(false)
+ expect(isEmptyObject(new Set())).toBe(false)
+ expect(isEmptyObject(new WeakMap())).toBe(false)
+ expect(isEmptyObject(new WeakSet())).toBe(false)
+ })
await it('Verify isArraySorted()', () => {
expect(
isArraySorted([], (a, b) => {
- return a - b;
- }),
- ).toBe(true);
+ return a - b
+ })
+ ).toBe(true)
expect(
isArraySorted([1], (a, b) => {
- return a - b;
- }),
- ).toBe(true);
- expect(isArraySorted<number>([1, 2, 3, 4, 5], (a, b) => a - b)).toBe(true);
- expect(isArraySorted<number>([1, 2, 3, 5, 4], (a, b) => a - b)).toBe(false);
- expect(isArraySorted<number>([2, 1, 3, 4, 5], (a, b) => a - b)).toBe(false);
- });
+ return a - b
+ })
+ ).toBe(true)
+ expect(isArraySorted<number>([1, 2, 3, 4, 5], (a, b) => a - b)).toBe(true)
+ expect(isArraySorted<number>([1, 2, 3, 5, 4], (a, b) => a - b)).toBe(false)
+ expect(isArraySorted<number>([2, 1, 3, 4, 5], (a, b) => a - b)).toBe(false)
+ })
await it('Verify once()', () => {
- let called = 0;
- const fn = () => ++called;
- const onceFn = once(fn, this);
- const result1 = onceFn();
- expect(called).toBe(1);
- expect(result1).toBe(1);
- const result2 = onceFn();
- expect(called).toBe(1);
- expect(result2).toBe(1);
- const result3 = onceFn();
- expect(called).toBe(1);
- expect(result3).toBe(1);
- });
+ let called = 0
+ const fn = (): number => ++called
+ const onceFn = once(fn, this)
+ const result1 = onceFn()
+ expect(called).toBe(1)
+ expect(result1).toBe(1)
+ const result2 = onceFn()
+ expect(called).toBe(1)
+ expect(result2).toBe(1)
+ const result3 = onceFn()
+ expect(called).toBe(1)
+ expect(result3).toBe(1)
+ })
await it('Verify min()', () => {
- expect(min()).toBe(Infinity);
- expect(min(0, 1)).toBe(0);
- expect(min(1, 0)).toBe(0);
- expect(min(0, -1)).toBe(-1);
- expect(min(-1, 0)).toBe(-1);
- });
+ expect(min()).toBe(Infinity)
+ expect(min(0, 1)).toBe(0)
+ expect(min(1, 0)).toBe(0)
+ expect(min(0, -1)).toBe(-1)
+ expect(min(-1, 0)).toBe(-1)
+ })
await it('Verify max()', () => {
- expect(max()).toBe(-Infinity);
- expect(max(0, 1)).toBe(1);
- expect(max(1, 0)).toBe(1);
- expect(max(0, -1)).toBe(0);
- expect(max(-1, 0)).toBe(0);
- });
-});
+ expect(max()).toBe(-Infinity)
+ expect(max(0, 1)).toBe(1)
+ expect(max(1, 0)).toBe(1)
+ expect(max(0, -1)).toBe(0)
+ expect(max(-1, 0)).toBe(0)
+ })
+})
-const { env } = require('node:process');
-const { defineConfig } = require('eslint-define-config');
+const { env } = require('node:process')
+const { defineConfig } = require('eslint-define-config')
module.exports = defineConfig({
root: true,
env: {
- node: true,
+ node: true
},
plugins: ['import'],
'plugin:import/recommended',
'plugin:vue/vue3-recommended',
'@vue/eslint-config-prettier',
- '@vue/eslint-config-typescript/recommended',
+ '@vue/eslint-config-typescript/recommended'
],
settings: {
'import/resolver': {
typescript: {
- project: './tsconfig.json',
- },
- },
+ project: './tsconfig.json'
+ }
+ }
},
parserOptions: {
- ecmaVersion: 'latest',
+ ecmaVersion: 'latest'
},
rules: {
'sort-imports': [
'error',
{
- ignoreDeclarationSort: true,
- },
+ ignoreDeclarationSort: true
+ }
],
- 'import/order': 'error',
- },
-});
+ 'import/order': 'error'
+ }
+})
export default {
'*.{.css,json,md,yml,yaml,html,js,jsx,cjs,mjs,ts,tsx,cts,mts}': 'prettier --cache --write',
'*.{vue,js,jsx,cjs,mjs,ts,tsx,cts,mts}':
- 'eslint . --cache --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore',
-};
+ 'eslint . --cache --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore'
+}
{
"$schema": "https://json.schemastore.org/prettierrc",
"printWidth": 100,
- "singleQuote": true
+ "semi": false,
+ "singleQuote": true,
+ "trailingComma": "none"
}
-import type { BaseConfig } from '@/types';
+import type { BaseConfig } from '@/types'
const config: BaseConfig = {
uiServer: {
host: 'localhost',
port: 8080,
- protocol: 'ui0.0.1',
- },
-};
+ protocol: 'ui0.0.1'
+ }
+}
-export default config;
+export default config
<script setup lang="ts">
const props = defineProps<{
- visibility: boolean;
-}>();
+ visibility: boolean
+}>()
-const emit = defineEmits(['close']);
+const emit = defineEmits(['close'])
function close() {
- emit('close');
+ emit('close')
}
</script>
</template>
<script setup lang="ts">
-import Button from '@/components/buttons/Button.vue';
+import Button from '@/components/buttons/Button.vue'
</script>
<style>
</template>
<script setup lang="ts">
-import FlatButton from '@/components/buttons/FlatButton.vue';
+import FlatButton from '@/components/buttons/FlatButton.vue'
const props = defineProps<{
- loading: boolean;
-}>();
+ loading: boolean
+}>()
</script>
<style>
</template>
<script setup lang="ts">
-// import { reactive } from 'vue';
-import Button from '../buttons/Button.vue';
-// import IdTagInputModal from './IdTagInputModal.vue';
-import type { ConnectorStatus } from '@/types';
-import { UIClient } from '@/composables/UIClient';
-// import { compose } from '@/composables/Utils';
+// import { reactive } from 'vue'
+import Button from '../buttons/Button.vue'
+// import IdTagInputModal from './IdTagInputModal.vue'
+import type { ConnectorStatus } from '@/types'
+import { UIClient } from '@/composables/UIClient'
+// import { compose } from '@/composables/Utils'
const props = defineProps<{
- hashId: string;
- connector: ConnectorStatus;
- connectorId: number;
- transactionId?: number;
- idTag?: string;
-}>();
+ hashId: string
+ connector: ConnectorStatus
+ connectorId: number
+ transactionId?: number
+ idTag?: string
+}>()
// type State = {
-// isIdTagModalVisible: boolean;
-// idTag: string;
-// transaction: () => void;
-// };
+// isIdTagModalVisible: boolean
+// idTag: string
+// transaction: () => void
+// }
// const state: State = reactive({
// isIdTagModalVisible: false,
// idTag: '',
-// transaction: startTransaction,
-// });
+// transaction: startTransaction
+// })
// function getIdTag(transaction: () => void): void {
-// state.transaction = transaction;
-// showTagModal();
+// state.transaction = transaction
+// showTagModal()
// }
// function showTagModal(): void {
-// state.isIdTagModalVisible = true;
+// state.isIdTagModalVisible = true
// }
// function hideIdTagModal(): void {
-// state.isIdTagModalVisible = false;
+// state.isIdTagModalVisible = false
// }
function startChargingStation(): void {
- UIClient.getInstance().startChargingStation(props.hashId);
+ UIClient.getInstance().startChargingStation(props.hashId)
}
function stopChargingStation(): void {
- UIClient.getInstance().stopChargingStation(props.hashId);
+ UIClient.getInstance().stopChargingStation(props.hashId)
}
function openConnection(): void {
- UIClient.getInstance().openConnection(props.hashId);
+ UIClient.getInstance().openConnection(props.hashId)
}
function closeConnection(): void {
- UIClient.getInstance().closeConnection(props.hashId);
+ UIClient.getInstance().closeConnection(props.hashId)
}
function startTransaction(): void {
- UIClient.getInstance().startTransaction(props.hashId, props.connectorId, props.idTag);
+ UIClient.getInstance().startTransaction(props.hashId, props.connectorId, props.idTag)
}
function stopTransaction(): void {
- UIClient.getInstance().stopTransaction(props.hashId, props.transactionId);
+ UIClient.getInstance().stopTransaction(props.hashId, props.transactionId)
}
function startAutomaticTransactionGenerator(): void {
- UIClient.getInstance().startAutomaticTransactionGenerator(props.hashId, props.connectorId);
+ UIClient.getInstance().startAutomaticTransactionGenerator(props.hashId, props.connectorId)
}
function stopAutomaticTransactionGenerator(): void {
- UIClient.getInstance().stopAutomaticTransactionGenerator(props.hashId, props.connectorId);
+ UIClient.getInstance().stopAutomaticTransactionGenerator(props.hashId, props.connectorId)
}
</script>
</template>
<script setup lang="ts">
-// import { reactive } from 'vue';
-import CSConnector from './CSConnector.vue';
-import type { ChargingStationData, ChargingStationInfo, ConnectorStatus } from '@/types';
-import { ifUndefined } from '@/composables/Utils';
+// import { reactive } from 'vue'
+import CSConnector from './CSConnector.vue'
+import type { ChargingStationData, ChargingStationInfo, ConnectorStatus } from '@/types'
+import { ifUndefined } from '@/composables/Utils'
const props = defineProps<{
- chargingStation: ChargingStationData;
- idTag: string;
-}>();
+ chargingStation: ChargingStationData
+ idTag: string
+}>()
// type State = {
-// isTagModalVisible: boolean;
-// idTag: string;
-// };
+// isTagModalVisible: boolean
+// idTag: string
+// }
// const state: State = reactive({
// isTagModalVisible: false,
-// idTag: '',
-// });
+// idTag: ''
+// })
function getConnectors(): ConnectorStatus[] {
if (Array.isArray(props.chargingStation.evses) && props.chargingStation.evses.length > 0) {
- const connectorsStatus: ConnectorStatus[] = [];
+ const connectorsStatus: ConnectorStatus[] = []
for (const [evseId, evseStatus] of props.chargingStation.evses.entries()) {
if (evseId > 0 && Array.isArray(evseStatus.connectors) && evseStatus.connectors.length > 0) {
for (const connectorStatus of evseStatus.connectors) {
- connectorsStatus.push(connectorStatus);
+ connectorsStatus.push(connectorStatus)
}
}
}
- return connectorsStatus;
+ return connectorsStatus
}
- return props.chargingStation.connectors?.slice(1);
+ return props.chargingStation.connectors?.slice(1)
}
function getInfo(): ChargingStationInfo {
- return props.chargingStation.stationInfo;
+ return props.chargingStation.stationInfo
}
function getHashId(): string {
- return getInfo().hashId;
+ return getInfo().hashId
}
function getId(): string {
- return ifUndefined<string>(getInfo().chargingStationId, 'Ø');
+ return ifUndefined<string>(getInfo().chargingStationId, 'Ø')
}
function getModel(): string {
- return getInfo().chargePointModel;
+ return getInfo().chargePointModel
}
function getVendor(): string {
- return getInfo().chargePointVendor;
+ return getInfo().chargePointVendor
}
function getFirmwareVersion(): string {
- return ifUndefined<string>(getInfo().firmwareVersion, 'Ø');
+ return ifUndefined<string>(getInfo().firmwareVersion, 'Ø')
}
function getStarted(): string {
- return props.chargingStation.started === true ? 'Yes' : 'No';
+ return props.chargingStation.started === true ? 'Yes' : 'No'
}
function getWsState(): string {
switch (props.chargingStation?.wsState) {
case WebSocket.CONNECTING:
- return 'Connecting';
+ return 'Connecting'
case WebSocket.OPEN:
- return 'Open';
+ return 'Open'
case WebSocket.CLOSING:
- return 'Closing';
+ return 'Closing'
case WebSocket.CLOSED:
- return 'Closed';
+ return 'Closed'
default:
- return 'Ø';
+ return 'Ø'
}
}
function getRegistrationStatus(): string {
- return props.chargingStation?.bootNotificationResponse?.status ?? 'Ø';
+ return props.chargingStation?.bootNotificationResponse?.status ?? 'Ø'
}
// function showTagModal(): void {
-// state.isTagModalVisible = true;
+// state.isTagModalVisible = true
// }
// function hideTagModal(): void {
-// state.isTagModalVisible = false;
+// state.isTagModalVisible = false
// }
</script>
</template>
<script setup lang="ts">
-import type { ChargingStationInfo } from '@/types';
-import Modal from '@/components/Modal.vue';
+import type { ChargingStationInfo } from '@/types'
+import Modal from '@/components/Modal.vue'
const props = defineProps<{
- stationInfo: ChargingStationInfo;
- isVisible: boolean;
-}>();
+ stationInfo: ChargingStationInfo
+ isVisible: boolean
+}>()
</script>
<style>
</template>
<script setup lang="ts">
-import CSData from './CSData.vue';
-import type { ChargingStationData } from '@/types';
+import CSData from './CSData.vue'
+import type { ChargingStationData } from '@/types'
const props = defineProps<{
- chargingStations: ChargingStationData[];
- idTag: string;
-}>();
+ chargingStations: ChargingStationData[]
+ idTag: string
+}>()
</script>
<style>
</template>
<script setup lang="ts">
-import Button from '../buttons/Button.vue';
-import Modal from '@/components/Modal.vue';
+import Button from '../buttons/Button.vue'
+import Modal from '@/components/Modal.vue'
const props = defineProps<{
- visibility: boolean;
- idTag: string;
-}>();
+ visibility: boolean
+ idTag: string
+}>()
-const emit = defineEmits(['done']);
+const emit = defineEmits(['done'])
function done() {
- emit('done');
+ emit('done')
}
</script>
type ProtocolResponse,
type RequestPayload,
type ResponsePayload,
- ResponseStatus,
-} from '@/types';
-import config from '@/assets/config';
+ ResponseStatus
+} from '@/types'
+import config from '@/assets/config'
type ResponseHandler = {
- procedureName: ProcedureName;
- resolve: (value: ResponsePayload | PromiseLike<ResponsePayload>) => void;
- reject: (reason?: unknown) => void;
-};
+ procedureName: ProcedureName
+ resolve: (value: ResponsePayload | PromiseLike<ResponsePayload>) => void
+ reject: (reason?: unknown) => void
+}
export class UIClient {
- private static instance: UIClient | null = null;
+ private static instance: UIClient | null = null
- private ws!: WebSocket;
- private responseHandlers: Map<string, ResponseHandler>;
+ private ws!: WebSocket
+ private responseHandlers: Map<string, ResponseHandler>
private constructor() {
- this.openWS();
- this.responseHandlers = new Map<string, ResponseHandler>();
+ this.openWS()
+ this.responseHandlers = new Map<string, ResponseHandler>()
}
public static getInstance() {
if (UIClient.instance === null) {
- UIClient.instance = new UIClient();
+ UIClient.instance = new UIClient()
}
- return UIClient.instance;
+ return UIClient.instance
}
public registerWSonOpenListener(listener: (event: Event) => void) {
- this.ws.addEventListener('open', listener);
+ this.ws.addEventListener('open', listener)
}
public async startSimulator(): Promise<ResponsePayload> {
- return this.sendRequest(ProcedureName.START_SIMULATOR, {});
+ return this.sendRequest(ProcedureName.START_SIMULATOR, {})
}
public async stopSimulator(): Promise<ResponsePayload> {
- return this.sendRequest(ProcedureName.STOP_SIMULATOR, {});
+ return this.sendRequest(ProcedureName.STOP_SIMULATOR, {})
}
public async listChargingStations(): Promise<ResponsePayload> {
- return this.sendRequest(ProcedureName.LIST_CHARGING_STATIONS, {});
+ return this.sendRequest(ProcedureName.LIST_CHARGING_STATIONS, {})
}
public async startChargingStation(hashId: string): Promise<ResponsePayload> {
- return this.sendRequest(ProcedureName.START_CHARGING_STATION, { hashIds: [hashId] });
+ return this.sendRequest(ProcedureName.START_CHARGING_STATION, { hashIds: [hashId] })
}
public async stopChargingStation(hashId: string): Promise<ResponsePayload> {
- return this.sendRequest(ProcedureName.STOP_CHARGING_STATION, { hashIds: [hashId] });
+ return this.sendRequest(ProcedureName.STOP_CHARGING_STATION, { hashIds: [hashId] })
}
public async openConnection(hashId: string): Promise<ResponsePayload> {
return this.sendRequest(ProcedureName.OPEN_CONNECTION, {
- hashIds: [hashId],
- });
+ hashIds: [hashId]
+ })
}
public async closeConnection(hashId: string): Promise<ResponsePayload> {
return this.sendRequest(ProcedureName.CLOSE_CONNECTION, {
- hashIds: [hashId],
- });
+ hashIds: [hashId]
+ })
}
public async startTransaction(
hashId: string,
connectorId: number,
- idTag: string | undefined,
+ idTag: string | undefined
): Promise<ResponsePayload> {
return this.sendRequest(ProcedureName.START_TRANSACTION, {
hashIds: [hashId],
connectorId,
- idTag,
- });
+ idTag
+ })
}
public async stopTransaction(
hashId: string,
- transactionId: number | undefined,
+ transactionId: number | undefined
): Promise<ResponsePayload> {
return this.sendRequest(ProcedureName.STOP_TRANSACTION, {
hashIds: [hashId],
- transactionId,
- });
+ transactionId
+ })
}
public async startAutomaticTransactionGenerator(
hashId: string,
- connectorId: number,
+ connectorId: number
): Promise<ResponsePayload> {
return this.sendRequest(ProcedureName.START_AUTOMATIC_TRANSACTION_GENERATOR, {
hashIds: [hashId],
- connectorIds: [connectorId],
- });
+ connectorIds: [connectorId]
+ })
}
public async stopAutomaticTransactionGenerator(
hashId: string,
- connectorId: number,
+ connectorId: number
): Promise<ResponsePayload> {
return this.sendRequest(ProcedureName.STOP_AUTOMATIC_TRANSACTION_GENERATOR, {
hashIds: [hashId],
- connectorIds: [connectorId],
- });
+ connectorIds: [connectorId]
+ })
}
private openWS(): void {
this.ws = new WebSocket(
`ws://${config.uiServer.host}:${config.uiServer.port}`,
- config.uiServer.protocol,
- );
- this.ws.onmessage = this.responseHandler.bind(this);
+ config.uiServer.protocol
+ )
+ this.ws.onmessage = this.responseHandler.bind(this)
this.ws.onerror = (errorEvent) => {
- console.error('WebSocket error: ', errorEvent);
- };
+ console.error('WebSocket error: ', errorEvent)
+ }
this.ws.onclose = (closeEvent) => {
- console.info('WebSocket closed: ', closeEvent);
- };
+ console.info('WebSocket closed: ', closeEvent)
+ }
}
private setResponseHandler(
id: string,
procedureName: ProcedureName,
resolve: (value: ResponsePayload | PromiseLike<ResponsePayload>) => void,
- reject: (reason?: unknown) => void,
+ reject: (reason?: unknown) => void
): void {
- this.responseHandlers.set(id, { procedureName, resolve, reject });
+ this.responseHandlers.set(id, { procedureName, resolve, reject })
}
private getResponseHandler(id: string): ResponseHandler | undefined {
- return this.responseHandlers.get(id);
+ return this.responseHandlers.get(id)
}
private deleteResponseHandler(id: string): boolean {
- return this.responseHandlers.delete(id);
+ return this.responseHandlers.delete(id)
}
private async sendRequest(
command: ProcedureName,
- data: RequestPayload,
+ data: RequestPayload
): Promise<ResponsePayload> {
return new Promise<ResponsePayload>((resolve, reject) => {
if (this.ws.readyState !== WebSocket.OPEN) {
- this.openWS();
+ this.openWS()
}
if (this.ws.readyState === WebSocket.OPEN) {
- const uuid = crypto.randomUUID();
- const msg = JSON.stringify([uuid, command, data]);
+ const uuid = crypto.randomUUID()
+ const msg = JSON.stringify([uuid, command, data])
const sendTimeout = setTimeout(() => {
- this.deleteResponseHandler(uuid);
- return reject(new Error(`Send request '${command}' message timeout`));
- }, 60 * 1000);
+ this.deleteResponseHandler(uuid)
+ return reject(new Error(`Send request '${command}' message timeout`))
+ }, 60 * 1000)
try {
- this.ws.send(msg);
- this.setResponseHandler(uuid, command, resolve, reject);
+ this.ws.send(msg)
+ this.setResponseHandler(uuid, command, resolve, reject)
} catch (error) {
- this.deleteResponseHandler(uuid);
- reject(error);
+ this.deleteResponseHandler(uuid)
+ reject(error)
} finally {
- clearTimeout(sendTimeout);
+ clearTimeout(sendTimeout)
}
} else {
- throw new Error(`Send request '${command}' message: connection not opened`);
+ throw new Error(`Send request '${command}' message: connection not opened`)
}
- });
+ })
}
private responseHandler(messageEvent: MessageEvent<string>): void {
- const response = JSON.parse(messageEvent.data) as ProtocolResponse;
+ const response = JSON.parse(messageEvent.data) as ProtocolResponse
if (Array.isArray(response) === false) {
- throw new Error(`Response not an array: ${JSON.stringify(response, undefined, 2)}`);
+ throw new Error(`Response not an array: ${JSON.stringify(response, undefined, 2)}`)
}
- const [uuid, responsePayload] = response;
+ const [uuid, responsePayload] = response
if (this.responseHandlers.has(uuid) === true) {
- const { procedureName, resolve, reject } = this.getResponseHandler(uuid)!;
+ const { procedureName, resolve, reject } = this.getResponseHandler(uuid)!
switch (responsePayload.status) {
case ResponseStatus.SUCCESS:
- resolve(responsePayload);
- break;
+ resolve(responsePayload)
+ break
case ResponseStatus.FAILURE:
- reject(responsePayload);
- break;
+ reject(responsePayload)
+ break
default:
console.error(
- `Response status for procedure '${procedureName}' not supported: '${responsePayload.status}'`,
- );
+ `Response status for procedure '${procedureName}' not supported: '${responsePayload.status}'`
+ )
}
- this.deleteResponseHandler(uuid);
+ this.deleteResponseHandler(uuid)
} else {
- throw new Error(`Not a response to a request: ${JSON.stringify(response, undefined, 2)}`);
+ throw new Error(`Not a response to a request: ${JSON.stringify(response, undefined, 2)}`)
}
}
}
const isUndefined = (value: unknown): boolean => {
- return typeof value === 'undefined';
-};
+ return typeof value === 'undefined'
+}
export const ifUndefined = <T>(value: T | undefined, isValue: T): T => {
- if (isUndefined(value) === true) return isValue;
- return value as T;
-};
+ if (isUndefined(value) === true) return isValue
+ return value as T
+}
// const isIterable = <T>(obj: T): boolean => {
// if (obj === null || obj === undefined) {
-// return false;
+// return false
// }
-// return typeof (obj as unknown as Iterable<T>)[Symbol.iterator] === 'function';
-// };
+// return typeof (obj as unknown as Iterable<T>)[Symbol.iterator] === 'function'
+// }
// const ifNotIterableDo = <T>(obj: T, cb: () => void): void => {
-// if (isIterable(obj) === false) cb();
-// };
+// if (isIterable(obj) === false) cb()
+// }
// export const compose = <T>(...fns: ((arg: T) => T)[]): ((x: T) => T) => {
-// return (x: T) => fns.reduceRight((y, fn) => fn(y), x);
-// };
+// return (x: T) => fns.reduceRight((y, fn) => fn(y), x)
+// }
-import { createApp } from 'vue';
-import App from './App.vue';
-import router from './router';
+import { createApp } from 'vue'
+import App from './App.vue'
+import router from './router'
-createApp(App).use(router).mount('#app');
+createApp(App).use(router).mount('#app')
-import { type RouteRecordRaw, createRouter, createWebHistory } from 'vue-router';
-import ChargingStationsView from '@/views/ChargingStationsView.vue';
+import { type RouteRecordRaw, createRouter, createWebHistory } from 'vue-router'
+import ChargingStationsView from '@/views/ChargingStationsView.vue'
const routes: RouteRecordRaw[] = [
{
path: '/',
name: 'charging-stations',
- component: ChargingStationsView,
- },
-];
+ component: ChargingStationsView
+ }
+]
const router = createRouter({
history: createWebHistory(),
- routes,
-});
+ routes
+})
-export default router;
+export default router
declare module '*.vue' {
- import type { DefineComponent } from 'vue';
+ import type { DefineComponent } from 'vue'
// eslint-disable-next-line @typescript-eslint/ban-types
- const component: DefineComponent<{}, {}, unknown>;
- export default component;
+ const component: DefineComponent<{}, {}, unknown>
+ export default component
}
-import type { JsonObject } from './JsonType';
+import type { JsonObject } from './JsonType'
export type ChargingStationData = {
- started: boolean;
- stationInfo: ChargingStationInfo;
- connectors: ConnectorStatus[];
- evses: EvseStatus[];
+ started: boolean
+ stationInfo: ChargingStationInfo
+ connectors: ConnectorStatus[]
+ evses: EvseStatus[]
wsState?:
| typeof WebSocket.CONNECTING
| typeof WebSocket.OPEN
| typeof WebSocket.CLOSING
- | typeof WebSocket.CLOSED;
- bootNotificationResponse?: BootNotificationResponse;
- automaticTransactionGenerator?: Status[];
-};
+ | typeof WebSocket.CLOSED
+ bootNotificationResponse?: BootNotificationResponse
+ automaticTransactionGenerator?: Status[]
+}
export enum OCPP16FirmwareStatus {
Downloaded = 'Downloaded',
Idle = 'Idle',
InstallationFailed = 'InstallationFailed',
Installing = 'Installing',
- Installed = 'Installed',
+ Installed = 'Installed'
}
export const FirmwareStatus = {
- ...OCPP16FirmwareStatus,
-} as const;
-export type FirmwareStatus = OCPP16FirmwareStatus;
+ ...OCPP16FirmwareStatus
+} as const
+export type FirmwareStatus = OCPP16FirmwareStatus
export type ChargingStationInfo = {
- hashId: string;
- chargingStationId?: string;
- chargePointModel: string;
- chargePointVendor: string;
- firmwareVersionPattern?: string;
- firmwareVersion?: string;
- firmwareStatus?: FirmwareStatus;
- numberOfConnectors?: number | number[];
- baseName: string;
- templateHash?: string;
- chargeBoxSerialNumber?: string;
- chargePointSerialNumber?: string;
- meterSerialNumber?: string;
- maximumPower?: number; // Always in Watt
- maximumAmperage?: number; // Always in Ampere
- supervisionUrls?: string | string[];
- supervisionUrlOcppConfiguration?: boolean;
- supervisionUrlOcppKey?: string;
- supervisionUser?: string;
- supervisionPassword?: string;
- ocppVersion?: OCPPVersion;
- ocppProtocol?: OCPPProtocol;
- ocppStrictCompliance?: boolean;
- ocppPersistentConfiguration?: boolean;
- stationInfoPersistentConfiguration?: boolean;
- idTagsFile?: string;
- nameSuffix?: string;
- fixedName?: boolean;
- iccid?: string;
- imsi?: string;
- meterType?: string;
- powerSharedByConnectors?: boolean;
- currentOutType?: CurrentType;
- voltageOut?: Voltage;
- numberOfPhases?: number;
- useConnectorId0?: boolean;
- randomConnectors?: boolean;
- resetTime?: number;
- autoRegister?: boolean;
- autoReconnectMaxRetries?: number;
- reconnectExponentialDelay?: boolean;
- registrationMaxRetries?: number;
- enableStatistics?: boolean;
- remoteAuthorization?: boolean;
- amperageLimitationOcppKey?: string;
- amperageLimitationUnit?: AmpereUnits;
- beginEndMeterValues?: boolean;
- outOfOrderEndMeterValues?: boolean;
- meteringPerTransaction?: boolean;
- transactionDataMeterValues?: boolean;
- mainVoltageMeterValues?: boolean;
- phaseLineToLineVoltageMeterValues?: boolean;
- customValueLimitationMeterValues?: boolean;
- commandsSupport?: CommandsSupport;
- messageTriggerSupport?: Record<MessageTrigger, boolean>;
-};
+ hashId: string
+ chargingStationId?: string
+ chargePointModel: string
+ chargePointVendor: string
+ firmwareVersionPattern?: string
+ firmwareVersion?: string
+ firmwareStatus?: FirmwareStatus
+ numberOfConnectors?: number | number[]
+ baseName: string
+ templateHash?: string
+ chargeBoxSerialNumber?: string
+ chargePointSerialNumber?: string
+ meterSerialNumber?: string
+ maximumPower?: number // Always in Watt
+ maximumAmperage?: number // Always in Ampere
+ supervisionUrls?: string | string[]
+ supervisionUrlOcppConfiguration?: boolean
+ supervisionUrlOcppKey?: string
+ supervisionUser?: string
+ supervisionPassword?: string
+ ocppVersion?: OCPPVersion
+ ocppProtocol?: OCPPProtocol
+ ocppStrictCompliance?: boolean
+ ocppPersistentConfiguration?: boolean
+ stationInfoPersistentConfiguration?: boolean
+ idTagsFile?: string
+ nameSuffix?: string
+ fixedName?: boolean
+ iccid?: string
+ imsi?: string
+ meterType?: string
+ powerSharedByConnectors?: boolean
+ currentOutType?: CurrentType
+ voltageOut?: Voltage
+ numberOfPhases?: number
+ useConnectorId0?: boolean
+ randomConnectors?: boolean
+ resetTime?: number
+ autoRegister?: boolean
+ autoReconnectMaxRetries?: number
+ reconnectExponentialDelay?: boolean
+ registrationMaxRetries?: number
+ enableStatistics?: boolean
+ remoteAuthorization?: boolean
+ amperageLimitationOcppKey?: string
+ amperageLimitationUnit?: AmpereUnits
+ beginEndMeterValues?: boolean
+ outOfOrderEndMeterValues?: boolean
+ meteringPerTransaction?: boolean
+ transactionDataMeterValues?: boolean
+ mainVoltageMeterValues?: boolean
+ phaseLineToLineVoltageMeterValues?: boolean
+ customValueLimitationMeterValues?: boolean
+ commandsSupport?: CommandsSupport
+ messageTriggerSupport?: Record<MessageTrigger, boolean>
+}
export enum OCPP16IncomingRequestCommand {
RESET = 'Reset',
REMOTE_START_TRANSACTION = 'RemoteStartTransaction',
REMOTE_STOP_TRANSACTION = 'RemoteStopTransaction',
GET_DIAGNOSTICS = 'GetDiagnostics',
- TRIGGER_MESSAGE = 'TriggerMessage',
+ TRIGGER_MESSAGE = 'TriggerMessage'
}
export const IncomingRequestCommand = {
- ...OCPP16IncomingRequestCommand,
-} as const;
-export type IncomingRequestCommand = OCPP16IncomingRequestCommand;
+ ...OCPP16IncomingRequestCommand
+} as const
+export type IncomingRequestCommand = OCPP16IncomingRequestCommand
export enum OCPP16RequestCommand {
BOOT_NOTIFICATION = 'BootNotification',
START_TRANSACTION = 'StartTransaction',
STOP_TRANSACTION = 'StopTransaction',
METER_VALUES = 'MeterValues',
- DIAGNOSTICS_STATUS_NOTIFICATION = 'DiagnosticsStatusNotification',
+ DIAGNOSTICS_STATUS_NOTIFICATION = 'DiagnosticsStatusNotification'
}
export const RequestCommand = {
- ...OCPP16RequestCommand,
-} as const;
-export type RequestCommand = OCPP16RequestCommand;
+ ...OCPP16RequestCommand
+} as const
+export type RequestCommand = OCPP16RequestCommand
-export type BootNotificationResponse = OCPP16BootNotificationResponse;
+export type BootNotificationResponse = OCPP16BootNotificationResponse
export enum OCPP16RegistrationStatus {
ACCEPTED = 'Accepted',
PENDING = 'Pending',
- REJECTED = 'Rejected',
+ REJECTED = 'Rejected'
}
export interface OCPP16BootNotificationResponse extends JsonObject {
- status: OCPP16RegistrationStatus;
- currentTime: Date;
- interval: number;
+ status: OCPP16RegistrationStatus
+ currentTime: Date
+ interval: number
}
export enum OCPP16MessageTrigger {
FirmwareStatusNotification = 'FirmwareStatusNotification',
Heartbeat = 'Heartbeat',
MeterValues = 'MeterValues',
- StatusNotification = 'StatusNotification',
+ StatusNotification = 'StatusNotification'
}
export const MessageTrigger = {
- ...OCPP16MessageTrigger,
-} as const;
-export type MessageTrigger = OCPP16MessageTrigger;
+ ...OCPP16MessageTrigger
+} as const
+export type MessageTrigger = OCPP16MessageTrigger
type CommandsSupport = {
- incomingCommands: Record<IncomingRequestCommand, boolean>;
- outgoingCommands?: Record<RequestCommand, boolean>;
-};
+ incomingCommands: Record<IncomingRequestCommand, boolean>
+ outgoingCommands?: Record<RequestCommand, boolean>
+}
export enum OCPPVersion {
VERSION_16 = '1.6',
- VERSION_20 = '2.0',
+ VERSION_20 = '2.0'
}
export enum OCPPProtocol {
- JSON = 'json',
+ JSON = 'json'
}
export enum CurrentType {
AC = 'AC',
- DC = 'DC',
+ DC = 'DC'
}
export enum Voltage {
VOLTAGE_110 = 110,
VOLTAGE_230 = 230,
VOLTAGE_400 = 400,
- VOLTAGE_800 = 800,
+ VOLTAGE_800 = 800
}
export enum AmpereUnits {
MILLI_AMPERE = 'mA',
CENTI_AMPERE = 'cA',
DECI_AMPERE = 'dA',
- AMPERE = 'A',
+ AMPERE = 'A'
}
export type ConnectorStatus = {
- availability: AvailabilityType;
- bootStatus?: ChargePointStatus;
- status?: ChargePointStatus;
- authorizeIdTag?: string;
- idTagAuthorized?: boolean;
- localAuthorizeIdTag?: string;
- idTagLocalAuthorized?: boolean;
- transactionRemoteStarted?: boolean;
- transactionStarted?: boolean;
- transactionId?: number;
- transactionIdTag?: string;
- energyActiveImportRegisterValue?: number; // In Wh
- transactionEnergyActiveImportRegisterValue?: number; // In Wh
-};
+ availability: AvailabilityType
+ bootStatus?: ChargePointStatus
+ status?: ChargePointStatus
+ authorizeIdTag?: string
+ idTagAuthorized?: boolean
+ localAuthorizeIdTag?: string
+ idTagLocalAuthorized?: boolean
+ transactionRemoteStarted?: boolean
+ transactionStarted?: boolean
+ transactionId?: number
+ transactionIdTag?: string
+ energyActiveImportRegisterValue?: number // In Wh
+ transactionEnergyActiveImportRegisterValue?: number // In Wh
+}
export type EvseStatus = {
- availability: AvailabilityType;
- connectors?: ConnectorStatus[];
-};
+ availability: AvailabilityType
+ connectors?: ConnectorStatus[]
+}
export enum OCPP16AvailabilityType {
INOPERATIVE = 'Inoperative',
- OPERATIVE = 'Operative',
+ OPERATIVE = 'Operative'
}
-export type AvailabilityType = OCPP16AvailabilityType;
+export type AvailabilityType = OCPP16AvailabilityType
export enum OCPP16ChargePointStatus {
AVAILABLE = 'Available',
FINISHING = 'Finishing',
RESERVED = 'Reserved',
UNAVAILABLE = 'Unavailable',
- FAULTED = 'Faulted',
+ FAULTED = 'Faulted'
}
-export type ChargePointStatus = OCPP16ChargePointStatus;
+export type ChargePointStatus = OCPP16ChargePointStatus
export type Status = {
- start?: boolean;
- startDate?: Date;
- lastRunDate?: Date;
- stopDate?: Date;
- stoppedDate?: Date;
- authorizeRequests?: number;
- acceptedAuthorizeRequests?: number;
- rejectedAuthorizeRequests?: number;
- startTransactionRequests?: number;
- acceptedStartTransactionRequests?: number;
- rejectedStartTransactionRequests?: number;
- stopTransactionRequests?: number;
- acceptedStopTransactionRequests?: number;
- rejectedStopTransactionRequests?: number;
- skippedConsecutiveTransactions?: number;
- skippedTransactions?: number;
-};
+ start?: boolean
+ startDate?: Date
+ lastRunDate?: Date
+ stopDate?: Date
+ stoppedDate?: Date
+ authorizeRequests?: number
+ acceptedAuthorizeRequests?: number
+ rejectedAuthorizeRequests?: number
+ startTransactionRequests?: number
+ acceptedStartTransactionRequests?: number
+ rejectedStartTransactionRequests?: number
+ stopTransactionRequests?: number
+ acceptedStopTransactionRequests?: number
+ rejectedStopTransactionRequests?: number
+ skippedConsecutiveTransactions?: number
+ skippedTransactions?: number
+}
export type BaseConfig = {
- uiServer: UIServerConfig;
-};
+ uiServer: UIServerConfig
+}
type UIServerConfig = {
- host: string;
- port: number;
- protocol: string;
- username?: string;
- password?: string;
-};
+ host: string
+ port: number
+ protocol: string
+ username?: string
+ password?: string
+}
-export type JsonType = JsonPrimitive | JsonType[] | JsonObject;
-export type JsonObject = { [key in string]?: JsonType };
-export type JsonPrimitive = string | number | boolean | Date | null;
+export type JsonType = JsonPrimitive | JsonType[] | JsonObject
+export type JsonObject = { [key in string]?: JsonType }
+export type JsonPrimitive = string | number | boolean | Date | null
-import type { JsonObject } from './JsonType';
+import type { JsonObject } from './JsonType'
export enum Protocol {
- UI = 'ui',
+ UI = 'ui'
}
export enum ApplicationProtocol {
HTTP = 'http',
- WS = 'ws',
+ WS = 'ws'
}
export enum ProtocolVersion {
- '0.0.1' = '0.0.1',
+ '0.0.1' = '0.0.1'
}
-export type ProtocolRequest = [string, ProcedureName, RequestPayload];
-export type ProtocolResponse = [string, ResponsePayload];
+export type ProtocolRequest = [string, ProcedureName, RequestPayload]
+export type ProtocolResponse = [string, ResponsePayload]
export type ProtocolRequestHandler = (
- payload: RequestPayload,
-) => ResponsePayload | Promise<ResponsePayload>;
+ payload: RequestPayload
+) => ResponsePayload | Promise<ResponsePayload>
export enum ProcedureName {
START_SIMULATOR = 'startSimulator',
START_AUTOMATIC_TRANSACTION_GENERATOR = 'startAutomaticTransactionGenerator',
STOP_AUTOMATIC_TRANSACTION_GENERATOR = 'stopAutomaticTransactionGenerator',
START_TRANSACTION = 'startTransaction',
- STOP_TRANSACTION = 'stopTransaction',
+ STOP_TRANSACTION = 'stopTransaction'
}
export interface RequestPayload extends JsonObject {
- hashIds?: string[];
- connectorIds?: number[];
+ hashIds?: string[]
+ connectorIds?: number[]
}
export enum ResponseStatus {
SUCCESS = 'success',
- FAILURE = 'failure',
+ FAILURE = 'failure'
}
export interface ResponsePayload extends JsonObject {
- status: ResponseStatus;
- hashIds?: string[];
+ status: ResponseStatus
+ hashIds?: string[]
}
export type {
ChargingStationData,
ChargingStationInfo,
- ConnectorStatus,
-} from './ChargingStationType';
-export type { BaseConfig } from './ConfigurationType';
+ ConnectorStatus
+} from './ChargingStationType'
+export type { BaseConfig } from './ConfigurationType'
export {
ProcedureName,
type ProtocolResponse,
type RequestPayload,
type ResponsePayload,
- ResponseStatus,
-} from './UIProtocol';
+ ResponseStatus
+} from './UIProtocol'
</template>
<script setup lang="ts">
-import { onMounted, reactive } from 'vue';
-import CSTable from '@/components/charging-stations/CSTable.vue';
-import type { ChargingStationData } from '@/types';
-import Container from '@/components/Container.vue';
-import ReloadButton from '@/components/buttons/ReloadButton.vue';
-import { UIClient } from '@/composables/UIClient';
+import { onMounted, reactive } from 'vue'
+import CSTable from '@/components/charging-stations/CSTable.vue'
+import type { ChargingStationData } from '@/types'
+import Container from '@/components/Container.vue'
+import ReloadButton from '@/components/buttons/ReloadButton.vue'
+import { UIClient } from '@/composables/UIClient'
-const UIClientInstance = UIClient.getInstance();
+const UIClientInstance = UIClient.getInstance()
onMounted(() => {
- UIClientInstance.registerWSonOpenListener(load);
-});
+ UIClientInstance.registerWSonOpenListener(load)
+})
type State = {
- isLoading: boolean;
- chargingStations: ChargingStationData[];
- idTag: string;
-};
+ isLoading: boolean
+ chargingStations: ChargingStationData[]
+ idTag: string
+}
const state: State = reactive({
isLoading: false,
chargingStations: [],
- idTag: '',
-});
+ idTag: ''
+})
async function load(): Promise<void> {
- if (state.isLoading === true) return;
- state.isLoading = true;
- const listChargingStationsPayload = await UIClientInstance.listChargingStations();
+ if (state.isLoading === true) return
+ state.isLoading = true
+ const listChargingStationsPayload = await UIClientInstance.listChargingStations()
state.chargingStations =
- listChargingStationsPayload.chargingStations as unknown as ChargingStationData[];
- state.isLoading = false;
+ listChargingStationsPayload.chargingStations as unknown as ChargingStationData[]
+ state.isLoading = false
}
function startSimulator(): void {
- UIClientInstance.startSimulator();
+ UIClientInstance.startSimulator()
}
function stopSimulator(): void {
- UIClientInstance.stopSimulator();
+ UIClientInstance.stopSimulator()
}
</script>
-import { createServer } from 'node:http';
-import { dirname, join } from 'node:path';
-import { env } from 'node:process';
-import { fileURLToPath } from 'node:url';
-import finalhandler from 'finalhandler';
-import serveStatic from 'serve-static';
+import { createServer } from 'node:http'
+import { dirname, join } from 'node:path'
+import { env } from 'node:process'
+import { fileURLToPath } from 'node:url'
+import finalhandler from 'finalhandler'
+import serveStatic from 'serve-static'
-const isCFEnvironment = env.VCAP_APPLICATION !== undefined,
- PORT = isCFEnvironment ? parseInt(env.PORT) : 3030,
- uiPath = join(dirname(fileURLToPath(import.meta.url)), './dist');
+const isCFEnvironment = env.VCAP_APPLICATION !== undefined
+const PORT = isCFEnvironment ? parseInt(env.PORT) : 3030
+const uiPath = join(dirname(fileURLToPath(import.meta.url)), './dist')
-const serve = serveStatic(uiPath);
+const serve = serveStatic(uiPath)
const server = createServer(function onRequest(req, res) {
- serve(req, res, finalhandler(req, res));
-});
+ serve(req, res, finalhandler(req, res))
+})
-server.listen(PORT, () => console.info(`App running at: http://localhost:${PORT}`));
+server.listen(PORT, () => console.info(`App running at: http://localhost:${PORT}`))
-import { expect, test } from 'vitest';
-import { shallowMount } from '@vue/test-utils';
-import CSTable from '@/components/charging-stations/CSTable.vue';
-import type { ChargingStationData } from '@/types';
+import { expect, test } from 'vitest'
+import { shallowMount } from '@vue/test-utils'
+import CSTable from '@/components/charging-stations/CSTable.vue'
+import type { ChargingStationData } from '@/types'
test('renders CS table columns name', () => {
- const chargingStations: ChargingStationData[] = [];
+ const chargingStations: ChargingStationData[] = []
const wrapper = shallowMount(CSTable, {
- props: { chargingStations, idTag: '0' },
- });
- expect(wrapper.text()).to.include('Action');
- expect(wrapper.text()).to.include('Connector');
- expect(wrapper.text()).to.include('Status');
- expect(wrapper.text()).to.include('Transaction');
- expect(wrapper.text()).to.include('Name');
- expect(wrapper.text()).to.include('Started');
- expect(wrapper.text()).to.include('WebSocket State');
- expect(wrapper.text()).to.include('Registration Status');
- expect(wrapper.text()).to.include('Vendor');
- expect(wrapper.text()).to.include('Model');
- expect(wrapper.text()).to.include('Firmware Version');
-});
+ props: { chargingStations, idTag: '0' }
+ })
+ expect(wrapper.text()).to.include('Action')
+ expect(wrapper.text()).to.include('Connector')
+ expect(wrapper.text()).to.include('Status')
+ expect(wrapper.text()).to.include('Transaction')
+ expect(wrapper.text()).to.include('Name')
+ expect(wrapper.text()).to.include('Started')
+ expect(wrapper.text()).to.include('WebSocket State')
+ expect(wrapper.text()).to.include('Registration Status')
+ expect(wrapper.text()).to.include('Vendor')
+ expect(wrapper.text()).to.include('Model')
+ expect(wrapper.text()).to.include('Firmware Version')
+})
-import { URL, fileURLToPath } from 'node:url';
-import { defineConfig } from 'vite';
-import vue from '@vitejs/plugin-vue';
-import vueJsx from '@vitejs/plugin-vue-jsx';
+import { URL, fileURLToPath } from 'node:url'
+import { defineConfig } from 'vite'
+import vue from '@vitejs/plugin-vue'
+import vueJsx from '@vitejs/plugin-vue-jsx'
export default defineConfig({
plugins: [vue(), vueJsx()],
resolve: {
alias: {
- '@': fileURLToPath(new URL('./src', import.meta.url)),
- },
- },
-});
+ '@': fileURLToPath(new URL('./src', import.meta.url))
+ }
+ }
+})
-import { fileURLToPath } from 'node:url';
-import { configDefaults, defineConfig } from 'vitest/config';
-import { mergeConfig } from 'vite';
-import viteConfig from './vite.config';
+import { fileURLToPath } from 'node:url'
+import { configDefaults, defineConfig } from 'vitest/config'
+import { mergeConfig } from 'vite'
+import viteConfig from './vite.config'
export default mergeConfig(
viteConfig,
root: fileURLToPath(new URL('./', import.meta.url)),
coverage: {
provider: 'v8',
- reporter: ['text', 'lcov'],
- },
- },
- }),
-);
+ reporter: ['text', 'lcov']
+ }
+ }
+ })
+)